第 42 章 - Go语言 设计模式

在Go语言中,设计模式是一种被广泛接受的解决常见问题的最佳实践。这些模式可以分为三类:创建型模式、结构型模式和行为型模式。下面我将结合案例以及源代码对这三种类型的设计模式进行详细讲解。

创建型模式

创建型模式主要关注对象的创建过程,使系统独立于如何创建、组合和表示对象。

1. 单例模式 (Singleton Pattern)

单例模式确保一个类只有一个实例,并提供一个全局访问点。

go 复制代码
package singleton

import "sync"

type Singleton struct {
    // 可以添加其他字段
}

var instance *Singleton
var once sync.Once

func GetInstance() *Singleton {
    once.Do(func() {
        instance = &Singleton{}
    })
    return instance
}
2. 工厂方法模式 (Factory Method Pattern)

工厂方法定义了一个创建对象的接口,但让子类决定实例化哪一个类。

go 复制代码
package factory

type Product interface {
    Use()
}

type ConcreteProductA struct{}

func (p *ConcreteProductA) Use() {
    fmt.Println("Using Product A")
}

type ConcreteProductB struct{}

func (p *ConcreteProductB) Use() {
    fmt.Println("Using Product B")
}

type Factory interface {
    CreateProduct() Product
}

type ConcreteFactoryA struct{}

func (f *ConcreteFactoryA) CreateProduct() Product {
    return &ConcreteProductA{}
}

type ConcreteFactoryB struct{}

func (f *ConcreteFactoryB) CreateProduct() Product {
    return &ConcreteProductB{}
}

结构型模式

结构型模式涉及如何组合类和对象以形成更大的结构。

1. 适配器模式 (Adapter Pattern)

适配器模式允许不同接口的对象通过适配器一起工作。

go 复制代码
package adapter

type Target interface {
    Request() string
}

type Adaptee struct{}

func (a *Adaptee) SpecificRequest() string {
    return "Specific request from Adaptee"
}

type Adapter struct {
    adaptee *Adaptee
}

func (a *Adapter) Request() string {
    return a.adaptee.SpecificRequest()
}
2. 装饰器模式 (Decorator Pattern)

装饰器模式允许动态地给一个对象添加新的功能。

go 复制代码
package decorator

type Component interface {
    Operation() string
}

type ConcreteComponent struct{}

func (c *ConcreteComponent) Operation() string {
    return "Base operation"
}

type Decorator struct {
    component Component
}

func (d *Decorator) Operation() string {
    return d.component.Operation() + " with additional functionality"
}

行为型模式

行为型模式关注对象之间的责任分配。

1. 观察者模式 (Observer Pattern)

观察者模式定义了对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知并自动更新。

go 复制代码
package observer

type Subject interface {
    Register(Observer)
    Deregister(Observer)
    NotifyAll()
}

type Observer interface {
    Update(string)
}

type ConcreteSubject struct {
    observers []Observer
}

func (s *ConcreteSubject) Register(o Observer) {
    s.observers = append(s.observers, o)
}

func (s *ConcreteSubject) Deregister(o Observer) {
    for i, obs := range s.observers {
        if obs == o {
            s.observers = append(s.observers[:i], s.observers[i+1:]...)
            break
        }
    }
}

func (s *ConcreteSubject) NotifyAll() {
    for _, observer := range s.observers {
        observer.Update("New message from subject")
    }
}

type ConcreteObserver struct{}

func (o *ConcreteObserver) Update(message string) {
    fmt.Println("Received:", message)
}

以上是几种常见的设计模式及其在Go语言中的实现示例。每种模式都有其特定的应用场景和优势,在实际开发中合理使用可以帮助提高代码质量和可维护性。

当然,我们可以继续探讨更多设计模式及其在Go语言中的实现。接下来我将介绍几种额外的设计模式。

结构型模式 (续)

3. 组合模式 (Composite Pattern)

组合模式允许你以一致的方式处理单个对象和对象组。

go 复制代码
package composite

type Component interface {
    Operation() string
}

type Leaf struct{}

func (l *Leaf) Operation() string {
    return "Leaf operation"
}

type Composite struct {
    children []Component
}

func (c *Composite) Add(child Component) {
    c.children = append(c.children, child)
}

func (c *Composite) Remove(child Component) {
    for i, comp := range c.children {
        if comp == child {
            c.children = append(c.children[:i], c.children[i+1:]...)
            break
        }
    }
}

func (c *Composite) Operation() string {
    var result string
    for _, child := range c.children {
        result += child.Operation()
    }
    return result
}

行为型模式 (续)

2. 策略模式 (Strategy Pattern)

策略模式定义了一系列算法,并将每个算法封装起来,使它们可以互换。

go 复制代码
package strategy

type Strategy interface {
    AlgorithmInterface()
}

type ConcreteStrategyA struct{}

func (s *ConcreteStrategyA) AlgorithmInterface() {
    fmt.Println("Algorithm A")
}

type ConcreteStrategyB struct{}

func (s *ConcreteStrategyB) AlgorithmInterface() {
    fmt.Println("Algorithm B")
}

type Context struct {
    strategy Strategy
}

func (c *Context) SetStrategy(strategy Strategy) {
    c.strategy = strategy
}

func (c *Context) ExecuteStrategy() {
    c.strategy.AlgorithmInterface()
}
3. 命令模式 (Command Pattern)

命令模式将请求封装成对象,从而让你可以用不同的请求、队列或者日志来参数化其他对象。

go 复制代码
package command

type Command interface {
    Execute()
}

type Receiver struct{}

func (r *Receiver) Action() {
    fmt.Println("Action performed by receiver")
}

type ConcreteCommand struct {
    receiver *Receiver
}

func (c *ConcreteCommand) Execute() {
    c.receiver.Action()
}

type Invoker struct {
    command Command
}

func (i *Invoker) SetCommand(command Command) {
    i.command = command
}

func (i *Invoker) Invoke() {
    i.command.Execute()
}

这些例子展示了如何使用Go语言实现不同的设计模式。每种模式都有其特定的适用场景,选择合适的模式能够帮助开发者构建更灵活、可扩展且易于维护的应用程序。

4. 状态模式 (State Pattern)

状态模式允许对象在其内部状态改变时改变其行为,看起来就像是改变了它的类一样。

go 复制代码
package state

type State interface {
    Handle(context *Context)
}

type Context struct {
    state State
}

func (c *Context) SetState(state State) {
    c.state = state
}

func (c *Context) Request() {
    c.state.Handle(c)
}

type ConcreteStateA struct{}

func (s *ConcreteStateA) Handle(context *Context) {
    fmt.Println("Handling in State A")
    // 过渡到另一个状态
    context.SetState(&ConcreteStateB{})
}

type ConcreteStateB struct{}

func (s *ConcreteStateB) Handle(context *Context) {
    fmt.Println("Handling in State B")
    // 可以过渡回State A或保持不变
}
5. 迭代器模式 (Iterator Pattern)

迭代器模式提供了一种方法来访问一个容器对象中的元素,而无需暴露其底层表示。

go 复制代码
package iterator

type Iterator interface {
    HasNext() bool
    Next() interface{}
}

type Aggregate interface {
    CreateIterator() Iterator
}

type ConcreteAggregate struct {
    items []interface{}
}

func (a *ConcreteAggregate) Add(item interface{}) {
    a.items = append(a.items, item)
}

func (a *ConcreteAggregate) CreateIterator() Iterator {
    return &ConcreteIterator{items: a.items, index: 0}
}

type ConcreteIterator struct {
    items []interface{}
    index int
}

func (i *ConcreteIterator) HasNext() bool {
    return i.index < len(i.items)
}

func (i *ConcreteIterator) Next() interface{} {
    if i.HasNext() {
        item := i.items[i.index]
        i.index++
        return item
    }
    return nil
}
6. 访问者模式 (Visitor Pattern)

访问者模式让你可以在不修改已有类的情况下添加新的操作。

go 复制代码
package visitor

type Visitor interface {
    VisitConcreteElementA(element *ConcreteElementA)
    VisitConcreteElementB(element *ConcreteElementB)
}

type Element interface {
    Accept(visitor Visitor)
}

type ConcreteElementA struct{}

func (e *ConcreteElementA) Accept(visitor Visitor) {
    visitor.VisitConcreteElementA(e)
}

type ConcreteElementB struct{}

func (e *ConcreteElementB) Accept(visitor Visitor) {
    visitor.VisitConcreteElementB(e)
}

type ConcreteVisitor1 struct{}

func (v *ConcreteVisitor1) VisitConcreteElementA(element *ConcreteElementA) {
    fmt.Println("ConcreteVisitor1 visits ConcreteElementA")
}

func (v *ConcreteVisitor1) VisitConcreteElementB(element *ConcreteElementB) {
    fmt.Println("ConcreteVisitor1 visits ConcreteElementB")
}

type ConcreteVisitor2 struct{}

func (v *ConcreteVisitor2) VisitConcreteElementA(element *ConcreteElementA) {
    fmt.Println("ConcreteVisitor2 visits ConcreteElementA")
}

func (v *ConcreteVisitor2) VisitConcreteElementB(element *ConcreteElementB) {
    fmt.Println("ConcreteVisitor2 visits ConcreteElementB")
}

这些例子进一步展示了Go语言中如何使用设计模式来解决特定问题。每一种模式都有其独特的优势和适用场景,选择合适的模式对于构建高效、可维护的软件系统至关重要。

7. 中介者模式 (Mediator Pattern)

中介者模式定义了一个封装了一系列对象交互的对象,使得这些对象不再直接相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

go 复制代码
package mediator

type Mediator interface {
    Notify(sender string, event string)
}

type ConcreteMediator struct {
    colleague1 *Colleague1
    colleague2 *Colleague2
}

func (m *ConcreteMediator) Notify(sender string, event string) {
    if sender == "Colleague1" && event == "A" {
        m.colleague2.React()
    } else if sender == "Colleague2" && event == "B" {
        m.colleague1.React()
    }
}

type Colleague interface {
    SetMediator(mediator Mediator)
    React()
}

type Colleague1 struct {
    mediator Mediator
}

func (c *Colleague1) SetMediator(mediator Mediator) {
    c.mediator = mediator
}

func (c *Colleague1) React() {
    fmt.Println("Colleague1 reacts")
    c.mediator.Notify("Colleague1", "A")
}

type Colleague2 struct {
    mediator Mediator
}

func (c *Colleague2) SetMediator(mediator Mediator) {
    c.mediator = mediator
}

func (c *Colleague2) React() {
    fmt.Println("Colleague2 reacts")
    c.mediator.Notify("Colleague2", "B")
}
8. 备忘录模式 (Memento Pattern)

备忘录模式在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后恢复对象到先前的状态。

go 复制代码
package memento

type Memento struct {
    state string
}

type Originator struct {
    state string
}

func (o *Originator) CreateMemento() *Memento {
    return &Memento{state: o.state}
}

func (o *Originator) RestoreFromMemento(m *Memento) {
    o.state = m.state
}

func (o *Originator) ChangeState(newState string) {
    o.state = newState
}

func (o *Originator) ShowState() {
    fmt.Printf("Current State: %s\n", o.state)
}

type Caretaker struct {
    mementos []*Memento
}

func (c *Caretaker) AddMemento(m *Memento) {
    c.mementos = append(c.mementos, m)
}

func (c *Caretaker) GetMemento(index int) *Memento {
    if index < len(c.mementos) {
        return c.mementos[index]
    }
    return nil
}
9. 解释器模式 (Interpreter Pattern)

解释器模式给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

go 复制代码
package interpreter

type Expression interface {
    Interpret(context string) bool
}

type TerminalExpression struct{}

func (te *TerminalExpression) Interpret(context string) bool {
    return context == "terminal"
}

type OrExpression struct {
    expr1, expr2 Expression
}

func (oe *OrExpression) Interpret(context string) bool {
    return oe.expr1.Interpret(context) || oe.expr2.Interpret(context)
}

type AndExpression struct {
    expr1, expr2 Expression
}

func (ae *AndExpression) Interpret(context string) bool {
    return ae.expr1.Interpret(context) && ae.expr2.Interpret(context)
}

通过上述例子,你可以看到如何在Go语言中应用各种行为型设计模式。每种模式都针对特定的问题提供了优雅的解决方案,有助于提高代码的质量和可维护性。希望这些信息对您有所帮助!

相关推荐
清酒伴风(面试准备中......)几秒前
Redis使用场景-缓存-缓存穿透
java·数据库·redis·缓存·面试·实习
速盾cdn2 分钟前
速盾高防cdn支持移动端独立缓存
开发语言·安全·web安全
懵懵懂懂程序员4 分钟前
Debezium Engine监听binlog实现缓存更新与业务解耦
java·spring boot·redis·缓存
暂时的1237 分钟前
一个十字翻转小游戏
前端·javascript·css·html
LG.YDX9 分钟前
java:拆箱和装箱,缓存池概念简单介绍
java·开发语言
束尘10 分钟前
页面内容下载为pdf
前端·javascript·pdf
kirito学长-Java10 分钟前
springboot/ssm大学校园生活信息平台Java校园活动论坛交流问卷系统web源码
java·开发语言·spring
Gordon家的哈士奇15 分钟前
设计模式之策略模式
java·设计模式·策略模式
编程修仙16 分钟前
I/O流程图
java·开发语言·流程图