更新於 2023/08/29閱讀時間約 7 分鐘

Golang - Design Pattern #19: 橋接模式 (Bridge)

raw-image
🌉 將抽象和實現分離 🌉

在許多複雜的程式設計問題中,如何將抽象與其具體實現分離開來,往往是一個重要的挑戰。橋接模式正是為了解決這樣的問題而生。透過橋接模式 (Bridge Pattern),不僅可以確保抽象和實現在結構上分離,還能提供一套彈性的機制來適應變化。接下來,我們將深入探討這一模式,並學習如何在 Go 語言中實現它。


橋接模式

橋接模式的主要目的是"分離抽象與實現",這樣在兩者獨立變化時,不會互相影響。此模式涉及到一個抽象接口,以及多個實現該接口的具體類。這使得你可以在不修改原始抽象類的情況下,更改或添加新的具體實現。


Go to Code ~~

🎨 不同的畫圖方法

假設我們有一個形狀Shape,它有多種不同的繪製方法(如繪製在螢幕上、打印等)。使用橋接模式,我們可以輕鬆地將Shape和繪製方法分離。


package main

import "fmt"

// DrawingAPI is the abstract "implementation" interface
type DrawingAPI interface {
DrawCircle(radius, x, y float64)
}

// Shape is the abstract "abstraction" class
type Shape interface {
Draw()
}

type CircleShape struct {
x, y, radius float64
drawingAPI DrawingAPI
}

func NewCircle(x, y, radius float64, drawingAPI DrawingAPI) *CircleShape {
return &CircleShape{x: x, y: y, radius: radius, drawingAPI: drawingAPI}
}

func (c *CircleShape) Draw() {
c.drawingAPI.DrawCircle(c.radius, c.x, c.y)
}

type DrawingAPI1 struct{}

func (da *DrawingAPI1) DrawCircle(radius, x, y float64) {
fmt.Printf("API1 draws circle at %f:%f radius %f\n", x, y, radius)
}

type DrawingAPI2 struct{}

func (da *DrawingAPI2) DrawCircle(radius, x, y float64) {
fmt.Printf("API2 draws circle at %f:%f radius %f\n", x, y, radius)
}

func main() {
// Usage
circle1 := NewCircle(1, 2, 3, &DrawingAPI1{})
circle1.Draw() // Output: API1 draws circle at 1.000000:2.000000 radius 3.000000

circle2 := NewCircle(1, 2, 3, &DrawingAPI2{})
circle2.Draw() // Output: API2 draws circle at 1.000000:2.000000 radius 3.000000
}


📩 消息發送

假設我們有一個消息發送系統,其中有不同的消息(如緊急消息、普通消息)和多種發送方式(如SMS、Email)。我們可以使用橋接模式將消息和發送方式分離。


package main

import "fmt"

// MessengerAPI is the abstract "implementation" interface
type MessengerAPI interface {
Send(message string, to string)
}

// Message is the abstract "abstraction" class
type Message interface {
Send()
}

type NormalMessage struct {
content string
to string
method MessengerAPI
}

func NewNormalMessage(content, to string, method MessengerAPI) *NormalMessage {
return &NormalMessage{content: content, to: to, method: method}
}

func (m *NormalMessage) Send() {
m.method.Send(m.content, m.to)
}

type UrgentMessage struct {
content string
to string
method MessengerAPI
}

func NewUrgentMessage(content, to string, method MessengerAPI) *UrgentMessage {
return &UrgentMessage{content: content, to: to, method: method}
}

func (m *UrgentMessage) Send() {
m.method.Send("[Urgent]"+m.content, m.to)
}

type SMSMessenger struct{}

func (sms *SMSMessenger) Send(message, to string) {
fmt.Printf("Sending SMS to %s: %s\n", to, message)
}

type EmailMessenger struct{}

func (email *EmailMessenger) Send(message, to string) {
fmt.Printf("Sending Email to %s: %s\n", to, message)
}

func main() {
// Usage
msg1 := NewNormalMessage("Hello, world!", "John", &SMSMessenger{})
msg1.Send() // Output: Sending SMS to John: Hello, world!

msg2 := NewUrgentMessage("System is down!", "Admin", &EmailMessenger{})
msg2.Send() // Output: Sending Email to Admin: [Urgent]System is down!
}


小結

橋接模式為我們提供了一個結構化的方法,幫助我們有效地分離抽象和實現。透過這一模式,我們可以確保當增加新的實現或修改現有實現時,不會對原有的抽象造成影響。而 Go 語言中的接口使得我們可以輕鬆地應用這一模式,創建高度靈活且可維護的代碼。🛠️

分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.