8.命令模式(Command Pattern)
命令模式是一种行为设计模式,它将一个请求或操作封装为一个对象。这种模式可以解耦请求的发送者和接收者,让它们不直接交互,而是通过命令对象来间接进行通信。
特点:
- 封装性:命令模式将请求封装为一个对象,隐藏了请求的具体实现细节。
- 扩展性:可以方便地添加新的命令类,无需修改现有代码。
- 灵活性:命令对象可以被存储、传递、排队、记录和修改。
优点:
- 降低了系统耦合度,请求发送者和接收者之间通过命令对象交互。
- 增加了操作的灵活性,如支持撤销、重做、事务等操作。
- 易于扩展,可以独立地添加新的命令。
缺点:
- 可能会有大量的命令类,特别是命令的实现逻辑复杂时。
应用场景:
- 事务处理:在需要支持事务操作的系统中,命令模式可以封装事务请求,支持事务的提交和回滚。
- 撤销操作:在需要撤销功能的系统中,命令对象可以存储状态,以便在需要时撤销操作。
- 日志请求:在需要记录用户操作的系统中,命令对象可以记录操作日志,用于审计或恢复操作。
- 批处理系统:在批处理系统中,命令对象可以表示一个批处理任务,支持任务的调度和执行。
- 宏录制:在需要宏录制功能的系统中,命令对象可以封装一系列操作,形成宏命令。
// 定义Command接口,它声明了所有具体命令必须实现的Execute方法
type Command interface {
Execute() // 执行命令的方法
}
// 定义Receiver结构体,它将执行命令的实际请求
type Receiver struct{}
func (r *Receiver) Action() {
fmt.Println("Receiver: Action")
}
// 定义ConcreteCommand结构体,它实现了Command接口
// 每个具体命令都包含一个Receiver的引用,表示请求的接收者
type ConcreteCommand struct {
receiver *Receiver // 命令执行的接收者
}
// ConcreteCommand实现Command接口的Execute方法
// 该方法调用Receiver的Action方法来执行请求
func (c *ConcreteCommand) Execute() {
c.receiver.Action() // 执行请求
}
// 定义Invoker结构体,它负责调用命令对象的Execute方法
type Invoker struct {
command Command // 存储命令对象
}
// 调用命令对象的Execute方法
func (i *Invoker) Invoke() {
i.command.Execute() // 执行命令
}
func main() {
// 创建接收者对象
receiver := &Receiver{}
// 创建具体命令对象,并注入接收者
command := &ConcreteCommand{receiver: receiver}
// 创建调用者对象,并注入具体命令对象
invoker := &Invoker{command: command}
// 调用者执行命令
invoker.Invoke() // 输出: Receiver: Action
}
9.组合模式(Composite Pattern)
组合模式是一种结构型设计模式,它允许你将对象组合成树状结构,以表示“部分-整体”的层次结构。这种模式使得用户可以一致地对待单个对象和对象组合。
特点:
- 部分-整体层次结构:可以包含其他组合或叶节点,形成树状结构。
- 一致性:客户端代码可以一致地处理组合结构和叶节点。
优点:
- 简化了客户端代码,客户端可以统一处理组合结构和对象。
- 更好的层次结构表示,易于扩展和维护。
缺点:
- 设计较复杂,需要合理地设计组件的接口和类。
应用场景:
- 文件系统:文件系统中的文件和文件夹可以形成树状结构,其中文件夹可以包含文件和其他文件夹。
- 组织结构:公司的组织结构可以表示为树状结构,其中每个部门可以包含员工和其他子部门。
- GUI组件:在图形用户界面开发中,组件可以包含其他组件,形成复杂的界面结构。
- 分布式系统:在分布式系统中,资源可以组合成树状结构,以方便管理和访问。
- 企业资源规划(ERP):ERP系统中,产品可以由多个部件组成,部件又可以进一步分解为子部件。
// 定义Component接口,作为组合中对象的一致性协议
type Component interface {
Operation() // 执行操作的方法
Add(Component) // 向组合中添加子节点的方法
Remove(Component) // 从组合中移除子节点的方法
GetChild(int) Component // 根据索引获取子节点的方法
}
// 定义Leaf结构体,表示组合中的叶节点
type Leaf struct {
name string
}
// Leaf实现Component接口的Operation方法
func (l *Leaf) Operation() {
fmt.Println("Leaf:", l.name)
}
// Leaf实现Component接口的Add方法,叶节点不能有子节点,因此这里可以不实现或抛出错误
func (l *Leaf) Add(c Component) {
fmt.Println("Cannot add to a leaf")
}
// Leaf实现Component接口的Remove方法,叶节点不能有子节点,因此这里可以不实现或抛出错误
func (l *Leaf) Remove(c Component) {
fmt.Println("Cannot remove from a leaf")
}
// Leaf实现Component接口的GetChild方法,叶节点没有子节点,因此这里返回nil
func (l *Leaf) GetChild(i int) Component {
return nil
}
// 定义Composite结构体,表示组合中的容器节点
type Composite struct {
name string
Children []Component // 存储子节点的列表
}
// Composite实现Component接口的Operation方法
func (c *Composite) Operation() {
fmt.Println("Composite:", c.name)
for _, child := range c.Children {
child.Operation() // 递归调用子节点的Operation方法
}
}
// Composite实现Component接口的Add方法,向Children列表中添加子节点
func (c *Composite) Add(component Component) {
c.Children = append(c.Children, component)
}
// Composite实现Component接口的Remove方法,从Children列表中移除子节点
func (c *Composite) Remove(component Component) {
for i, child := range c.Children {
if child == component {
c.Children = append(c.Children[:i], c.Children[i+1:]...)
break
}
}
}
// Composite实现Component接口的GetChild方法,根据索引获取子节点
func (c *Composite) GetChild(i int) Component {
if i < 0 || i >= len(c.Children) {
return nil // 索引超出范围,返回nil
}
return c.Children[i]
}
func main() {
// 创建叶节点
leafA := &Leaf{name: "Leaf A"}
leafB := &Leaf{name: "Leaf B"}
// 创建组合节点
composite := &Composite{name: "Composite Root"}
composite.Add(leafA) // 向组合中添加叶节点A
composite.Add(leafB) // 向组合中添加叶节点B
// 执行组合节点的操作
composite.Operation()
}
10.迭代器模式(Iterator Pattern)
迭代器模式是一种行为设计模式,它允许你顺序访问一个聚合对象中的各个元素而不需要暴露其内部的表示。迭代器模式提供了一种通过抽象迭代器来遍历元素的方法,使得你可以在不知道具体集合类型的情况下,对集合进行遍历。
特点:
- 抽象化遍历过程:迭代器定义了遍历元素的接口。
- 支持多种遍历方式:不同的迭代器可以实现不同的遍历策略。
- 聚合对象与迭代器解耦:聚合对象不需要知道迭代器的具体实现。
优点:
- 抽象化集合的访问,使客户端代码与集合的内部表示无关。
- 可以提供多种遍历方式,如正序或逆序遍历。
- 增加了集合的灵活性,可以在不修改集合类的情况下,引入新的遍历方式。
缺点:
- 增加了系统的复杂性,需要为每个聚合类设计迭代器类。
- 需要额外的代码来实现迭代器。
应用场景:
- 遍历集合:在需要遍历集合元素的系统中,迭代器模式提供了一种通用的遍历机制。
- 数据结构:在实现复杂的数据结构如树、图等时,迭代器模式可以用来遍历结构中的节点。
- 数据库查询:在数据库查询中,迭代器可以用来逐条访问查询结果。
- 用户界面:在用户界面开发中,迭代器可以用来遍历界面元素。
- 多维数组访问:在需要访问多维数组元素的系统中,迭代器可以提供一种顺序访问的方式。
// 定义Iterator接口,它声明了迭代器必须实现的Next和Current方法
type Iterator interface {
Next() bool // 移动到下一个元素,并返回是否成功移动
Current() interface{} // 返回当前元素
}
// 定义ConcreteIterator结构体,它实现了Iterator接口
type ConcreteIterator struct {
items []string // 存储聚合对象的元素列表
index int // 当前迭代到的元素索引
}
// Next方法实现,用于移动到下一个元素
func (c *ConcreteIterator) Next() bool {
if c.index < len(c.items) {
c.index++ // 索引递增
return true
}
return false // 如果索引超出范围,返回false
}
// Current方法实现,用于返回当前元素
func (c *ConcreteIterator) Current() interface{} {
if c.index > 0 && c.index <= len(c.items) {
return c.items[c.index-1] // 返回当前索引的元素
}
return nil // 如果索引不在范围内,返回nil
}
// 定义Aggregate接口,表示聚合对象,它将负责创建迭代器
type Aggregate interface {
CreateIterator() Iterator // 创建并返回迭代器
}
// 定义ConcreteAggregate结构体,它实现了Aggregate接口
type ConcreteAggregate struct {
items []string // 聚合对象存储的元素列表
}
// CreateIterator方法实现,用于创建并返回一个迭代器
func (a *ConcreteAggregate) CreateIterator() Iterator {
return &ConcreteIterator{items: a.items, index: 0} // 返回一个新的迭代器实例
}
func main() {
// 创建聚合对象并添加元素
aggregate := &ConcreteAggregate{items: []string{"Item1", "Item2", "Item3"}}
// 使用聚合对象创建迭代器
iterator := aggregate.CreateIterator()
// 使用迭代器遍历聚合对象中的所有元素
for iterator.Next() {
fmt.Println(iterator.Current())
}
}