Golang 演示 10 種設計模式

作者:knightwwang

golang 演示常見的十種設計模式的應用場景。

1. 單例模式(Singleton Pattern)

單例模式是一種創建型設計模式,它限制了實例化類的對象個數,確保在任何情況下,一個類只有一個實例,並且提供一個全局訪問點。這種模式在需要全局狀態控制或共享資源訪問時非常有用。

特點:

優點:

缺點:

應用場景:

// 定義一個結構體Singleton,用於存儲單例的實例數據
type singleton struct {
 value string // 這裏可以存儲單例對象的任何數據
}

// 定義一個全局變量instance,用於存儲單例的實例
var instance *singleton

// getInstance函數用於獲取單例的實例
// 如果instance爲nil,則創建一個新的singleton實例
// 否則,返回已存在的實例
func getInstance() *singleton {
 if instance == nil {
     instance = &singleton{value: "unique instance"} // 這裏初始化singleton實例
 }
 return instance // 返回單例的實例
}

func main() {
 // 獲取單例的實例
 singletonInstance := getInstance()
 fmt.Println(singletonInstance.value) // 輸出: unique instance

 // 再次獲取單例的實例,將返回相同的實例
 anotherInstance := getInstance()
 if singletonInstance == anotherInstance {
     fmt.Println("Both instances are the same") // 輸出: Both instances are the same
 }
}

在併發環境下如果沒有適當的同步機制,多個 goroutine 可能會同時檢測到instancenil並嘗試創建新的實例,從而導致創建多個實例。 爲了解決這個問題,可以使用sync.Once,它確保在併發環境中只執行一次初始化操作。

// 定義一個結構體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) // 輸出: unique instance

    // 再次獲取單例的實例,將返回相同的實例
    anotherInstance := getInstance()
    if singletonInstance == anotherInstance {
        fmt.Println("Both instances are the same") // 輸出: Both instances are the same
    }
    
    // 測試併發環境下的單例模式
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            singletonInstance := getInstance()
            fmt.Println(singletonInstance.value)
        }()
    }
    wg.Wait()
}

2. 工廠模式(Factory Pattern)

工廠模式是一種創建型設計模式,用於將對象的創建過程封裝起來,由子類決定實例化哪一個類。這種模式使得代碼結構更加清晰,並且能夠輕鬆替換或擴展產品類。

特點:

優點:

缺點:

應用場景:

// 定義一個接口Product,它聲明瞭所有具體產品對象必須實現的操作
type Product interface {
 operation() // 產品對象的操作
}

// 定義具體產品ConcreteProductA,實現了Product接口
type ConcreteProductA struct{}
func (p *ConcreteProductA) operation() {
 fmt.Println("Operation of ConcreteProductA")
}

// 定義另一個具體產品ConcreteProductB,也實現了Product接口
type ConcreteProductB struct{}
func (p *ConcreteProductB) operation() {
 fmt.Println("Operation of ConcreteProductB")
}

// 定義一個抽象工廠Creator,它聲明瞭工廠方法factoryMethod,用於創建產品對象
type Creator interface {
 factoryMethod() Product // 工廠方法,用於創建產品對象
}

// 定義具體工廠CreatorA,實現了Creator接口
type CreatorA struct{}
func (c *CreatorA) factoryMethod() Product {
 return &ConcreteProductA{} // 具體工廠CreatorA返回ConcreteProductA的實例
}

// 定義另一個具體工廠CreatorB,也實現了Creator接口
type CreatorB struct{}
func (c *CreatorB) factoryMethod() Product {
 return &ConcreteProductB{} // 具體工廠CreatorB返回ConcreteProductB的實例
}

func main() {
 // 創建具體工廠CreatorA的實例
 creatorA := &CreatorA{}
 productA := creatorA.factoryMethod()
 productA.operation() // 調用產品A的操作

 // 創建具體工廠CreatorB的實例
 creatorB := &CreatorB{}
 productB := creatorB.factoryMethod()
 productB.operation() // 調用產品B的操作
}

3. 觀察者模式(Observer Pattern)

觀察者模式是一種行爲設計模式,它定義了對象間的一種一對多的依賴關係,使得當一個對象改變狀態時,所有依賴於它的對象都會得到通知並自動更新。這種模式非常適合於實現分佈式事件處理系統。

特點:

優點:

缺點:

應用場景:

// 定義Observer接口,它聲明瞭觀察者需要實現的Update方法
type Observer interface {
 Update(string) // 當主題狀態改變時,此方法會被調用
}

// 定義Subject結構體,它包含一個觀察者列表和方法來添加或通知觀察者
type Subject struct {
 observers []Observer // 存儲觀察者的列表
}

// Attach方法用於將一個觀察者添加到觀察者列表中
func (s *Subject) Attach(observer Observer) {
 s.observers = append(s.observers, observer)
}

// Notify方法用於通知所有觀察者主題狀態的改變
func (s *Subject) Notify(message string) {
 for _, observer := range s.observers {
     observer.Update(message) // 調用每個觀察者的Update方法
 }
}

// 定義一個具體觀察者ConcreteObserver,它實現了Observer接口
type ConcreteObserverA struct {
 name string
}

// 實現Observer接口的Update方法
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)

裝飾者模式是一種結構型設計模式,允許用戶在不修改對象自身的基礎上,通過添加裝飾者對象來動態地給對象添加額外的職責或功能。

特點:

優點:

缺點:

應用場景:

// 定義Component接口,它是所有組件和裝飾者的基類
type Component interface {
 operation() // 組件執行的操作
}

// 定義具體組件ConcreteComponent,實現了Component接口
type ConcreteComponent struct{}
func (c *ConcreteComponent) operation() {
 fmt.Println("ConcreteComponent: performing basic operation")
}

// 定義Decorator抽象結構體,它包含一個Component接口類型的字段
type Decorator struct {
 component Component // 用於組合Component接口
}

// 實現Decorator的operation方法,調用其Component的operation方法
func (d *Decorator) operation() {
 if d.component != nil {
     d.component.operation() // 調用被裝飾者的operation
 }
}

// 定義具體裝飾者ConcreteDecoratorA,它嵌入了Decorator結構體
type ConcreteDecoratorA struct {
 Decorator // 繼承Decorator,實現裝飾功能
}

// 爲ConcreteDecoratorA實現operation方法,添加額外的職責
func (cda *ConcreteDecoratorA) operation() {
 cda.Decorator.operation() // 首先調用被裝飾者的operation
 fmt.Println("ConcreteDecoratorA: added additional responsibilities")
}

func main() {
 // 創建具體組件
 component := &ConcreteComponent{}

 // 創建裝飾者並關聯具體組件
 decoratorA := &ConcreteDecoratorA{Decorator{component}}

 // 執行裝飾後的組件操作
 decoratorA.operation()
}

5. 策略模式(Strategy Pattern)

策略模式是一種行爲設計模式,它定義了一系列的算法,並將每一個算法封裝起來,使它們可以互相替換。策略模式讓算法獨立於使用它的客戶端。

特點:

優點:

缺點:

應用場景:

// 定義Strategy接口,它聲明瞭所有具體策略必須實現的algorithm方法
type Strategy interface {
 algorithm() // 策略的算法方法
}

// 定義具體策略ConcreteStrategyA,實現了Strategy接口
type ConcreteStrategyA struct{}
func (c *ConcreteStrategyA) algorithm() {
 fmt.Println("Executing Algorithm A")
}

// 定義另一個具體策略ConcreteStrategyB,也實現了Strategy接口
type ConcreteStrategyB struct{}
func (c *ConcreteStrategyB) algorithm() {
 fmt.Println("Executing Algorithm B")
}

// 定義Context結構體,它包含一個Strategy接口類型的字段
type Context struct {
 strategy Strategy // 用於存儲當前使用的策略
}

// 執行策略的方法,通過Context中的strategy字段調用algorithm方法
func (c *Context) executeStrategy() {
 c.strategy.algorithm() // 執行當前策略的算法
}

func main() {
 // 創建Context對象
 context := &Context{}

 // 創建具體策略對象
 strategyA := &ConcreteStrategyA{}
 strategyB := &ConcreteStrategyB{}

 // 將Context的策略設置爲策略A
 context.strategy = strategyA
 context.executeStrategy() // 輸出: Executing Algorithm A

 // 更換策略爲策略B
 context.strategy = strategyB
 context.executeStrategy() // 輸出: Executing Algorithm B
}

6. 適配器模式(Adapter Pattern)

適配器模式是一種結構型設計模式,用於使原本不兼容的接口能夠一起工作。它通常涉及到一個客戶端使用一個期望的特定接口,而另一個類或組件提供了一個不同的接口。適配器模式通過創建一箇中間層(適配器),將一個類的接口轉換成客戶端期望的另一個接口。

特點:

優點:

缺點:

應用場景:

// 定義Target接口,表示客戶端使用的特定領域相關的接口
type Target interface {
 request() // 客戶端期望調用的方法
}

// 定義一個已經存在的類Adaptee,它有自己的接口
type Adaptee struct{}
func (a *Adaptee) specificRequest() {
 fmt.Println("Adaptee performs a specific request")
}

// 定義Adapter結構體,它作爲Target接口和Adaptee類之間的橋樑
type Adapter struct {
 adaptee *Adaptee // 引用Adaptee對象
}

// Adapter實現了Target接口的request方法
// 該方法內部委託給Adaptee的specificRequest方法
func (a *Adapter) request() {
 if a.adaptee != nil {
     a.adaptee.specificRequest() // 委託調用Adaptee的方法
 }
}

func main() {
 // 創建Adaptee對象
 adaptee := &Adaptee{}

 // 創建Adapter對象,並注入Adaptee對象
 adapter := &Adapter{adaptee: adaptee}

 // 客戶端使用Target接口,這裏通過Adapter實現
 var target Target = adapter
 target.request() // 通過Adapter調用Adaptee的方法
}

7. 代理模式(Proxy Pattern)

代理模式是一種結構型設計模式,它爲另一個對象提供一個代替或佔位符,以控制對它的訪問。代理可以在不改變對象的代碼前提下,通過引入代理對象來間接訪問原始對象,從而在不直接暴露原始對象的情況下,提供額外的功能操作。

特點:

優點:

缺點:

應用場景:

// 定義一個Subject接口,它聲明瞭真實主題和代理主題共有的接口。
type Subject interface {
 request() // 聲明一個請求方法,真實主題和代理主題都會實現這個方法。
}

// RealSubject 結構體實現了 Subject 接口,代表真實主題。
type RealSubject struct{}

// RealSubject 的 request 方法實現了 Subject 接口的 request 方法,用於執行實際的操作。
func (r *RealSubject) request() {
 fmt.Println("Real Subject") // 打印 "Real Subject" 表示真實主題正在被調用。
}

// Proxy 結構體包含一個指向 RealSubject 的指針,它作爲代理主題。
type Proxy struct {
 realSubject *RealSubject // 代理主題包含一個對真實主題的引用,初始爲 nil。
}

// Proxy 的 request 方法實現了 Subject 接口的 request 方法。
// 這個方法首先檢查 realSubject 是否爲 nil,如果是,則創建 RealSubject 的實例。
// 然後,調用 realSubject 的 request 方法,從而間接地實現了 Subject 接口的 request 方法。
func (p *Proxy) request() {
 if p.realSubject == nil { // 如果 realSubject 爲 nil,說明還沒有創建真實主題的實例。
     p.realSubject = &RealSubject{} // 創建 RealSubject 的實例,並賦值給 realSubject。
 }
 p.realSubject.request() // 調用真實主題的 request 方法。
}

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)

組合模式是一種結構型設計模式,它允許你將對象組合成樹狀結構,以表示 “部分 - 整體” 的層次結構。這種模式使得用戶可以一致地對待單個對象和對象組合。

特點:

優點:

缺點:

應用場景:

// 定義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())
 }
}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/sZuQwV-cSao5sfvkr6u45w