其精神在於降低abstraction和implementor之間的coupling(耦合度)
讓abstraction在延伸子類別時,
不用擔心因為implementor的改變,而須修改子類別的程式碼。
接下來,使用正反兩個例子來說明bridge pattern。
要設計Android上的遊戲叫做AngryBee,要怎麼做呢?
反面例子
聖誕節快到了,應景推出AngryBee的聖誕節版本,於是多了以下類別:
過了不久,Android的版本由froyo升級成gingerbread了,這對上述程式有何影響呢?
因為AngryBee的子類別,FreeVersion & XmasVersion都使用Froyo,
所以須要修改這兩個類別的程式碼。
日後,若AngryBee下增加PaidVersion的子類別,其下又包含XmasVersion的子類別,
那麼當Android的版本又變動時,就必須要修改四個類別的程式碼。
改善方式
那要如何改善這種情況呢?
我們可以發現,
會變動的是AngryBee(會有不斷延伸的子類別)和Android(會有不同的版本)
因此,首要之務,
就是把這兩個會變動的部份加以區隔,降低兩者之間的耦合度(coupling),
使雙方能夠各自變動(例如延伸子類別,或提供不同的實作),
而不會變動到對方的程式碼。
亦即設法達到鬆散耦合(loose coupling)。
即然耦合是鬆散的,表示兩者之間仍然有關係存在,
這關係就是 bridge pattern中的bridge,
透過這座bridge連接會變動的雙方,
透過bridge降低耦合度,
透過bridge增加程式的彈性。
正面例子
透過AngryBee(abstraction)和Platform(implementor)的連結,
Platform的實作有所異動時,不會影響到AngryBee的子類別中的程式碼。
兩者之間的變更,不會影響彼此的程式碼。
bridge vesus strategy
雖然bridge和strategy的UML圖看起來一樣,但兩者有著本質上的不同。
bridge pattern是用來設計編譯時期的結構,
strategy是用來設計執行時期的行為。
以此例來說,使用何種版本的android platform,是在編譯時期就決定好的,
不會在執行的時候才決定要用froyo或gingerbread,
因此套用在這個例子上的模式是bridge pattern。
其他例子
java.awt中,有不少使用bridge pattern的例子,
例如:
在Windows, Linux, MacOS中都會去實作以下的類別,
java.awt.Container
└ java.awt.Window
└ java.awt.Dialog
└ java.awt.FileDialog
而不同作業系統的實作方式並不相同。
這時候就會使用bridge pattern來讓abstraction與implementor分離。
延伸閱讀
Strategy Pattern(策略模式)
Factory Pattern(工廠模式)
讚!!
回覆刪除