🌉 將抽象和實現分離 🌉
在許多複雜的程式設計問題中,如何將抽象與其具體實現分離開來,往往是一個重要的挑戰。橋接模式正是為了解決這樣的問題而生。透過橋接模式 (Bridge Pattern),不僅可以確保抽象和實現在結構上分離,還能提供一套彈性的機制來適應變化。接下來,我們將深入探討這一模式,並學習如何在 Go 語言中實現它。
橋接模式的主要目的是"分離抽象與實現",這樣在兩者獨立變化時,不會互相影響。此模式涉及到一個抽象接口,以及多個實現該接口的具體類。這使得你可以在不修改原始抽象類的情況下,更改或添加新的具體實現。
假設我們有一個形狀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 語言中的接口使得我們可以輕鬆地應用這一模式,創建高度靈活且可維護的代碼。🛠️