切换语言为:繁体

十大经典设计模式在GO语言中的实现

  • 爱糖宝
  • 2024-09-05
  • 2048
  • 0
  • 0

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())
    }
}

这些设计模式是软件工程中常用的解决方案,可以帮助开发者提高代码的可重用性、可读性和可靠性。

0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.