小孩子在5,6歲的時候是很有創造力和想像力的,而且很喜歡"跟風",看見鄰居家小孩買了新的玩具,一定要嚷嚷著父母給買一個.父母坳不過就買吧,今天一輛小汽車,明天一個大房子,於是乎沒完沒了了,幾個月下來小孩子屋裡全是玩具.
有一天父母給他買了一套積木,可把小孩給樂的,每天在屋子裡不停的擺停著,一會組裝個小橋,一會組裝個小汽車出來,玩的不亦樂乎啊,從此父母得到了消停.
看來現在的大人們早已深知組合的魅力啊!孩子們呢從組合中開發了思維,又樂在其中.
今天講的Bridge模式就是通過一個組合的技術給你一個解決子類膨脹的漂亮方案.
Bridge模式的實現非常簡單,就是通過組合的方式達到給抽象和具體化解耦.
Bridge模式個人在實際代碼中見到很少,但其體現的OO思想是很豐富的,可挖掘的東西很多.
首先,談剛才講到的解耦.所謂解耦就是把兩個直接依賴的方面,通過增加一層,變成間接依賴,支援動態行為.這一手段必將引入另一個很重要的思想,面向介面編程.通過引入一個介面層,使得原來不可分開的"抽象"和"具體化",變得沒有直接依賴.
其次,解釋下為什麼要面向介面編程,也就是所謂的具體應該依賴於抽象,抽象不應該依賴於具體.以前自己剛進公司的時候,主管就讓我們先熟習下部門主打產品的結構,那個時候頭痛的很,一大堆的介面,不知從哪裡入手.跟著跟著,就又進了介面,都不知道實際上執行了哪些東東,具體是怎麼實現.唯有運行程式,一步步跟進的時候,噢才明白原來調用了哪些哪些方法,但這個時候更容易陷入細枝末節上,缺乏對架構整體的把握.當時的想法就是好複雜啊,為什麼定義這麼多的介面,可把我害苦了.
我想這個過程也是很多初學者走過的.現在我來回答你為什麼要面向介面編程: 解耦,還是解耦.那為什麼我們要解耦.低耦合高內聚為什麼如此重要,以至於經常聽到別人左一句解耦,右一句解耦的,用來衡量你的設計,衡量產品的品質呢.解耦的目的就是在於隔離(廢話,跟沒講似的).隔離的目的在於更好地封裝.我以為軟體開發就是一個適應需求變化的過程,如何有效適應這個需求不斷變化的時代,封裝對就是封裝.封裝就像個縮放鏡,可以把某個變化無限縮小,以至於外界絲毫感覺不出你已經變化了.這裡說到解耦的最終目的就是有效地封裝變化,抵抗需求變化.這句話還隱含的一個意思就是,我們並不要做到什麼地方都解耦,唯有容易變化的地方才需要解耦.那些穩定的地方是不需要解耦的.否則容易過度設計,必將自食其果.實際上也不存在完全解耦的軟體.通用定義一個抽象的介面Implementor,解耦了Abstraction和ConcreteImplementor的關係.然而帶來的卻是Abstraction依賴於Implementor,這個也就是所謂的耦合.那麼為什麼這裡是可以,原因在於我們認為介面是種契約,是穩定的是不易變化的,具體實現是容易變化的.如果介面都需要改變,那麼說明你抽象出來的介面定義有問題,否則無論你用Gof的什麼模式都沒法很好地解決你變化的問題,誇張的說整個系統是沒法有效封裝變化,是很脆弱的,很難擴充的.(所幸我們一般都能夠抽象出穩定的介面,其穩定的程度在於你的設計經驗,對領域相關的知識瞭解)
接著再羅嗦一下封裝.封裝是OOP的3大概念之一,不要以為你真的瞭解了這3個概念,不要以為你真的融會貫通OOP思想.實際上大部分我們都不清楚,認識的都不夠徹底. (m2,這裡只是講講我的理解而已,大家補充).最開始覺得封裝很好理解,把成員私人化,不讓外面訪問,不就是封裝嗎.其實遠非如此.一個Property封裝了field;一個函數封裝了實現的細節;一個類封裝了職責,等等...這些都是不同細度的封裝.真正的意思也許隱藏的更深.(封裝用來抵抗變化??)
接著聊,Bridge體現了單一職責原則.為什麼可以使用Bridge模式,為什麼能夠使用組合的手段,原因在於這個類存在的多個變化點.SRP:就一個類而言,應該僅有一個引起它變化的原因.
來自呂震宇舉的非常通俗易懂的蠟筆和毛筆故事.引起蠟筆子類膨脹問題的原因就是蠟筆的職責不夠單一,存在大小,和顏色這兩個不同方向上的變化.而毛筆的設計就有效地把兩個變化點各自封裝在不同的對象上.職責單一,而且更好理解實現.
最後,優先使用組合原則.這個好處重要性不用再說了吧.要是還沒有達到這一共識,這篇文章就算白扯了.
最後的最後,當然這裡OCP原則也少不了.(LSP原則呢,個人感覺這個主要在於設計語言的時候用吧,另一個地方就是用于衡量兩個類之間可否有繼承關係的時候,如橢圓和圓因為違反了LSP原則,所以圓不能繼承自橢圓)
模式比較:
與Strategy策略模式比較, Strategy主要是在單個支點上變化,主體邏輯保持不變.
與Decorator裝飾者模式比較, 兩者都能夠有效地解決子類膨脹的問題,但兩者在結構上,在應用場合上是完全不同的.Decorator的核心在於互相裝飾,體現在某一功能上的擴充(注意"某一功能"這個詞,這個體現了其區別另一個模式的地方,以後談到Decorator的時候再講). n個裝飾類產生的效果,不只是n*n種組合. n*n*n, n*n*n*n都是無限可能的,其組合方式從概念上來講是無限大的(無限互相裝飾的效果). Strategy呢只是用 M*N 替代 M + N,其組合方式是有限的,類的結構決定了他們組合方式的個數,也決定了他們適應的場合.
主要參考資料:
•李建忠, Webcast設計模式系列
•閻宏,《Java與模式》,電子工業出版社
•呂震宇, 設計模式隨筆-蠟筆與毛筆的故事
•idior , Bridge Strategy 和State的區別
忘記了最值得推薦的一本書 : <<敏捷式軟體開發 (Agile Software Development)>> Bob大叔