切換語言為:簡體

十大經典設計模式在GO語言中的實現

  • 爱糖宝
  • 2024-09-05
  • 2047
  • 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.