橋接模式是一種結構型設計模式,通過橋接模式可以將抽象部分和它的實現部分分離。這看著有點兒奇怪,接下來會作詳細說明。
橋接模式建議將一個較大的類拆分成兩中角色。
- 抽象角色 - 抽象角色是一個介面。它的子類也被稱為修正抽象角色。抽象角色包含一個對實現角色的引用。
- 實現角色 - 實現角色也是一個介面。實現角色的子類被稱為具化實現角色。
這樣分層的優勢在於在呼叫抽象角色的時候不需要考慮實現層的內容。
舉個例子,假設我們手上有兩部筆記本:Mac本和Windows本;同時也有兩部印表機:愛普生(Epson)印表機和惠普(Hp)印表機。我們希望筆記本和印表機能任意組合來完成工作,使用者只通過筆記本進行操作而無需關心印表機是如何工作的。
這個例子中有2×2四種組合,但是不需要為此建立四個struct,而是建立兩層:
- 抽象層
- 實現層
看下下面的圖。在圖中可以看到抽象層(這裡是computer)和實現層(這裡是printer)通過抽象層中對實現層的引用來進行互動,這個引用就是橋接模式所謂的橋樑。通過橋接模式,抽象層和引用層可以分別獨立實現而不互相影響。
注意圖中win和mac是如何嵌入printer的引用的:這裡繫結的是printer介面,而非是priter的具體實現。這樣就可以在執行時修改printer的值。如前面所說,printer引用在這裡扮演了一個橋樑的角色,並實現了computer和printer的鬆耦合。
橋接模式的UML圖如下:
接下來是前面的例子的程式碼。
抽象角色,computer.go:
type computer interface { print() setPrinter(printer) }
修正抽象角色1,win.go
import "fmt" type windows struct { printer printer } func (w *windows) print() { fmt.Println("Print request for windows") w.printer.printFile() } func (w *windows) setPrinter(p printer) { w.printer = p }
修正抽象角色2,mac.go
import "fmt" type mac struct { printer printer } func (m *mac) print() { fmt.Println("Print request for mac") m.printer.printFile() } func (m *mac) setPrinter(p printer) { m.printer = p }
實現角色,printer.go
type printer interface { printFile() }
具體實現角色1,epson.go
import "fmt" type epson struct { } func (p *epson) printFile() { fmt.Println("Printing by a EPSON Printer") }
具體實現角色2,hp.go
type hp struct { } func (p *hp) printFile() { fmt.Println("Printing by a HP Printer") }
Client, main.go
func main() { hpPrinter := &hp{} epsonPrinter := &epson{} macComputer := &mac{} macComputer.setPrinter(hpPrinter) macComputer.print() fmt.Println() macComputer.setPrinter(epsonPrinter) macComputer.print() fmt.Println() winComputer := &windows{} winComputer.setPrinter(hpPrinter) winComputer.print() fmt.Println() winComputer.setPrinter(epsonPrinter) winComputer.print() fmt.Println() }
輸出內容:
Print request for mac Printing by a HP Printer Print request for mac Printing by a EPSON Printer Print request for windows Printing by a HP Printer Print request for windows Printing by a EPSON Printer
程式碼已上傳至GitHub: zhyea / go-patterns / bridge-pattern
END!