1. 单例模式(Singleton Pattern)
特点:确保一个类只有一个实例,并提供一个全局访问点。
优点:保证资源或状态的全局唯一性,减少资源消耗。
缺点:反模块化,测试困难。
应用场景:配置管理器、连接池、日志记录器等。
代码示例:
type singleton struct { value string } var instance *singleton // 定义一个结构体Singleton,用于存储单例的实例数据 type singleton struct { value string // 这里可以存储单例对象的任何数据 } // 定义一个Once对象,用于确保初始化操作只执行一次 var once sync.Once // 定义一个全局变量instance,用于存储单例的实例 var instance *singleton // 初始化函数,由Once.Do调用 func initSingleton() { instance = &singleton{value: "unique instance"} // 这里初始化singleton实例 } // getInstance函数用于获取单例的实例 func getInstance() *singleton { // 执行initSingleton,确保instance只被初始化一次 once.Do(initSingleton) return instance // 返回单例的实例 } func main() { // 获取单例实例 singletonInstance := getInstance() fmt.Println(singletonInstance.value) // 再次获取单例实例,将返回相同的实例 anotherInstance := getInstance() if singletonInstance == anotherInstance { fmt.Println("Both instances are the same") } }
2. 工厂模式(Factory Pattern)
特点:封装对象创建过程,由子类决定实例化哪个类。
优点:提高模块独立性,易于扩展。
缺点:类数量可能急剧增加,工厂类可能过于庞大。
应用场景:数据库连接、GUI组件、支付网关等。
代码示例:
// 定义产品接口,声明了所有具体产品对象必须实现的操作 type Product interface { operation() } // 定义具体产品实现接口 type ConcreteProductA struct{} func (p *ConcreteProductA) operation() { fmt.Println("Operation of ConcreteProductA") } // 定义抽象工厂接口,声明了工厂方法 type Creator interface { factoryMethod() Product } // 定义具体工厂实现接口 type CreatorA struct{} func (c *CreatorA) factoryMethod() Product { return &ConcreteProductA{} // 返回具体产品的实例 } func main() { // 使用工厂创建产品 creatorA := &CreatorA{} productA := creatorA.factoryMethod() productA.operation() }
3. 观察者模式(Observer Pattern)
特点:定义对象间一对多的依赖关系,自动更新依赖对象。
优点:降低耦合度,扩展性好。
缺点:可能造成性能问题,系统难以维护。
应用场景:事件监听系统、UI更新、消息系统等。
代码示例:
// 定义观察者接口,声明了更新方法 type Observer interface { Update(string) } // 定义主题,包含观察者列表和注册、通知观察者的方法 type Subject struct { observers []Observer } func (s *Subject) Attach(observer Observer) { s.observers = append(s.observers, observer) } func (s *Subject) Notify(message string) { for _, observer := range s.observers { observer.Update(message) // 通知所有观察者 } } // 定义具体观察者实现接口 type ConcreteObserverA struct { name string } func (c *ConcreteObserverA) Update(message string) { fmt.Printf("%s received message: %s\n", c.name, message) } func main() { subject := &Subject{} observerA := &ConcreteObserverA{name: "Observer A"} subject.Attach(observerA) // 注册观察者 subject.Notify("State changed to State 1") // 通知观察者 }
4. 装饰者模式(Decorator Pattern)
特点:动态地给对象添加额外职责或功能。
优点:增加职责动态且可撤销,多个装饰者可组合使用。
缺点:系统复杂,可能影响性能。
应用场景:日志记录、缓存、安全控制等。
代码示例:
// 定义组件接口,声明了组件的操作 type Component interface { operation() } // 定义具体组件实现接口 type ConcreteComponent struct{} func (c *ConcreteComponent) operation() { fmt.Println("ConcreteComponent: performing basic operation") } // 定义装饰者抽象类,包含组件接口类型的字段 type Decorator struct { component Component } // 装饰者实现组件的操作,委托给组件 func (d *Decorator) operation() { if d.component != nil { d.component.operation() } } // 定义具体装饰者实现装饰者抽象类 type ConcreteDecoratorA struct { Decorator } func (cda *ConcreteDecoratorA) operation() { cda.Decorator.operation() // 调用装饰的组件操作 fmt.Println("ConcreteDecoratorA: added additional responsibilities") } func main() { component := &ConcreteComponent{} decoratorA := &ConcreteDecoratorA{Decorator{component}} decoratorA.operation() // 装饰后的操作 }
5. 策略模式(Strategy Pattern)
特点:定义算法家族,封装起来,互相替换。
优点:算法变化独立于客户端,易于添加新算法。
缺点:客户端需要了解策略类差异。
应用场景:算法选择、支付方式、排序算法等。
代码示例:
// 定义策略接口,声明了策略的算法方法 type Strategy interface { algorithm() } // 定义具体策略实现接口 type ConcreteStrategyA struct{} func (c *ConcreteStrategyA) algorithm() { fmt.Println("Executing Algorithm A") } // 定义上下文环境,包含策略接口类型的字段 type Context struct { strategy Strategy } // 上下文环境执行策略的方法 func (c *Context) executeStrategy() { c.strategy.algorithm() } func main() { context := &Context{} strategyA := &ConcreteStrategyA{} context.strategy = strategyA // 设置策略 context.executeStrategy() // 执行策略 }
6. 适配器模式(Adapter Pattern)
特点:使不兼容接口能一起工作。
优点:增加兼容性,客户端代码无需修改。
缺点:系统复杂,可能引入性能开销。
应用场景:系统集成、第三方库集成等。
代码示例:
// 定义客户端期望的接口 type Target interface { request() } // 定义一个已经存在的类,有自己的接口 type Adaptee struct{} func (a *Adaptee) specificRequest() { fmt.Println("Adaptee performs a specific request") } // 定义适配器,作为Target接口和Adaptee类之间的桥梁 type Adapter struct { adaptee *Adaptee } func (a *Adapter) request() { if a.adaptee != nil { a.adaptee.specificRequest() // 委托调用Adaptee的方法 } } func main() { adaptee := &Adaptee{} adapter := &Adapter{adaptee: adaptee} var target Target = adapter // 客户端通过适配器使用Adaptee target.request() }
7. 代理模式(Proxy Pattern)
特点:为另一个对象提供代替或占位符,控制访问。
优点:降低耦合度,增加可控性,代码可扩展。
缺点:增加系统复杂性,可能引入性能开销。
应用场景:访问控制、延迟初始化、远程代理等。
代码示例:
// 定义主题接口,声明了请求方法 type Subject interface { request() } // 定义真实主题,实现了主题接口 type RealSubject struct{} func (r *RealSubject) request() { fmt.Println("Real Subject") } // 定义代理主题,包含对真实主题的引用 type Proxy struct { realSubject *RealSubject } func (p *Proxy) request() { if p.realSubject == nil { p.realSubject = &RealSubject{} // 如果没有真实主题,则创建一个 } p.realSubject.request() // 调用真实主题的请求方法 }
8. 命令模式(Command Pattern)
特点:将请求或操作封装为对象,解耦发送者和接收者。
优点:降低耦合度,增加操作灵活性,易于扩展。
缺点:可能产生大量命令类。
应用场景:事务处理、撤销操作、日志请求等。
代码示例:
// 定义命令接口,声明了执行方法 type Command interface { Execute() } // 定义接收者,将执行命令的实际请求 type Receiver struct{} func (r *Receiver) Action() { fmt.Println("Receiver: Action") } // 定义具体命令,实现命令接口,包含接收者的引用 type ConcreteCommand struct { receiver *Receiver } func (c *ConcreteCommand) Execute() { c.receiver.Action() // 执行接收者的操作 } // 定义调用者,负责调用命令对象的执行方法 type Invoker struct { command Command } func (i *Invoker) Invoke() { i.command.Execute() // 执行命令 } func main() { receiver := &Receiver{} command := &ConcreteCommand{receiver: receiver} // 创建具体命令对象,并注入接收者 invoker := &Invoker{command: command} // 创建调用者对象,并注入具体命令对象 invoker.Invoke() // 调用者执行命令 }
9. 组合模式(Composite Pattern)
特点:将对象组合成树状结构,一致对待单个对象和组合。
优点:简化客户端代码,更好的层次结构表示。
缺点:设计复杂,需要合理设计接口和类。
应用场景:文件系统、组织结构、GUI组件等。
代码示例:
// 定义组件接口,作为组合中对象的一致性协议 type Component interface { Operation() Add(Component) Remove(Component) GetChild(int) Component } // 定义叶节点,实现组件接口 type Leaf struct { name string } func (l *Leaf) Operation() { fmt.Println("Leaf:", l.name) } func (l *Leaf) Add(c Component) { fmt.Println("Cannot add to a leaf") } func (l *Leaf) Remove(c Component) { fmt.Println("Cannot remove from a leaf") } func (l *Leaf) GetChild(i int) Component { return nil } // 定义组合节点,实现组件接口 type Composite struct { name string Children []Component } func (c *Composite) Operation() { fmt.Println("Composite:", c.name) for _, child := range c.Children { child.Operation() } } func (c *Composite) Add(component Component) { c.Children = append(c.Children, component) } 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 } } } func (c *Composite) GetChild(i int) Component { if i < 0 || i >= len(c.Children) { return 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)
特点:顺序访问聚合对象元素,不暴露内部表示。
优点:抽象化集合访问,支持多种遍历方式,增加灵活性。
缺点:增加系统复杂性,需要额外代码实现迭代器。
应用场景:遍历集合、数据结构、数据库查询等。
代码示例:
// 定义迭代器接口,声明了遍历集合的方法 type Iterator interface { Next() bool // 移动到下一个元素 Current() interface{} // 返回当前元素 } // 定义具体迭代器实现接口 type ConcreteIterator struct { items []string // 存储聚合对象的元素列表 index int // 当前迭代到的元素索引 } func (c *ConcreteIterator) Next() bool { if c.index < len(c.items) { c.index++ return true } return false } func (c *ConcreteIterator) Current() interface{} { if c.index > 0 && c.index <= len(c.items) { return c.items[c.index-1] } return nil } // 定义聚合对象接口,声明了创建迭代器的方法 type Aggregate interface { CreateIterator() Iterator // 创建并返回迭代器 } // 定义具体聚合对象实现接口 type ConcreteAggregate struct { items []string // 聚合对象存储的元素列表 } 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()) } }
这些设计模式是软件工程中常用的解决方案,可以帮助开发者提高代码的可重用性、可读性和可靠性。