很多程式員用面向對象語言寫了多年的代碼, 仍然不知道設計模式為何物, 這不奇怪, 設計模式并不是非有不可,可是它能讓代碼變的更美好。
程式員大可悶頭堆代碼, 複制粘貼, 然後不斷的感慨代碼難以維護, 難以複用, 難以擴充, 而繼續不思進取。
當然也可以選折不斷去追求更美好, 更合理的代碼, 把自己從bug調試, 需求變動等噩夢中拯救出來, 進而真正體會到編碼的樂趣。
你如果選折後者那麼設計模式對于你而言, 是真正必不可少的, 隻有當你真正認真考慮過代碼的複用性,擴充性,和合理性時, 你才能真正體會到設計模式的好處。
想知道一樣東西的價值, 最好的方法就是想想, 如果沒有它, 你會怎麼樣.
對于學習模式, 也是一樣, 不要拘泥于其中, 要多想想為什麼需要它. 如果沒有這種模式, 一樣是很好的code, 那就說明這個模式在這種情況下沒有價值, 那就不要去用他.
如果使用了一種模式, 能使你的code從可擴充性, 可維護性和可複用性上有些提高, 那麼這個就是他的價值所在.
下面是面向對象設計的7大原則,是學習程式設計和模式的基礎
單一職責原則 (srp)
一個類,隻有一個引起它變化的原因。應該隻有一個職責。如果一個類有一個以上的職責,這些職責就耦合在了一起。這會導緻脆弱的設計。當一個職責發生變化時,可能會影響其它的職責. 這嚴重影響了代碼的可維護性, 可複用性.
開閉原則(ocp)
開閉原則是面向對象設計中“可複用設計”的基石,是面向對象設計中最重要的原則之一,其它很多的設計原則都是實作開閉原則的一種手段。1988 年,bertrand meyer在他的著作《object oriented software construction》中提出了開閉原則,它的原文是這樣:“software entities should be open for extension,but closed for modification”。翻譯過來就是:“軟體實體應當對擴充開放,對修改關閉”。一句好說不好做的話......
依賴倒置原則(dip)
依賴倒置原則(dependence inversion principle)就是要依賴于抽象,不要依賴于具體。簡單的說就是要求對抽象進行程式設計,不要對實作進行程式設計,這樣就降低了客戶與實作子產品間的耦合。
a.高層次的子產品不應該依賴于低層次的子產品,他們都應該依賴于抽象。
b.抽象不應該依賴于具體,具體應該依賴于抽象。
依賴倒置原則的本質就是通過抽象(接口或者抽象類)使各個類或模型的實作彼此獨立,不互相影響,實作子產品間的松耦合。
接口隔離原則(isp)
接口是我們設計時對外提供的契約,通過分散定義多個接口,可以預防未來變更的擴散,提高系統的靈活性和可維護性。
要求在接口中盡量少公布public方法,而不是建立一個龐大的臃腫的接口,容納所有的用戶端通路。
接口是對外的承諾,承諾地越少對系統開發越有利,變更的風險也就越少,同時也有利于降低成本。
迪米特法則(lod,lkp)
迪米特法則(law of demeter,lod)也稱為最少知識原則(least knowledge principle,lkp), 迪米特法則的核心觀念就是類間解耦,弱耦合. 一個類應該對自己需要耦合或調用的類知道得最少,你(被耦合或調用的類)的内部是如何複雜都和我沒關系,那是你的事情,我就知道你提供的public方 法,我就調用這麼多,其他的一概不關心。
設計模式的門面模式(facade)和中介模式(mediator),都是迪米特法則應用的例子。
裡氏替換原則 (lsp)
liskov 于1987年提出了一個關于繼承的原則“inheritance should ensure that any property proved about supertype objects also holds for subtype objects.”——“繼承必須確定超類所擁有的性質在子類中仍然成立。”也就是說,當一個子類的執行個體應該能夠替換任何其超類的執行個體時,它們之間才具有 is-a關系。 該原則稱為liskov substitution principle——裡氏替換原則。
繼承是個耦合性很強的關系, 是以不能随便輕率的使用繼承關系, 如果子類并不能完全替換父類的話, 應該使用聚集, 組合來代替繼承.
舉個例子, 鳥-->企鵝, 可是企鵝不會飛, 無法實作fly函數, 這樣的繼承關系就違反了裡氏替換原則.
合成/聚合複用原則(carp)
合成/聚合複用原則(composite/aggregate reuse principle)的核心思想就是:要盡量使用合成/聚合,不要濫用繼承.
說到這, 先來談談aggregation(聚合關系)和composition(組合關系)
aggregation(聚合關系), 一種弱的'擁有'關系, 比如人群和人, 就是一般的list和list item, 即表示集合和個體的關系, 用空心的菱形表示
composition(組合關系), 一種強的'擁有'關系, 比如人和腿, 它們具有相同的生命周期, 即表示整體和部分的關系, 用實心的菱形表示
一般遇到的都是聚合關系, 組合關系隻是聚合關系的一個特例. 組合模式(composite)也是基于聚合關系來讨論的(雖然叫composite模式).
繼承作為面向對象的基礎, 非常強大和重要, 但是濫用繼承也會帶來很多問題, 是以我們要明确區分"is-a"和"has-a"關系.
"is-a"是嚴格的分類學意義上定義,意思是一個類是另一個類的"一種"。而"has-a"則不同,它表示某一個角色具有某一項責任。導緻錯誤的使用繼承而不是合成/聚合的一個常見的原因是錯誤的把"has-a"當作"is-a"。是以隻有真正存在"is-a"關系時, 我們才考慮使用繼承, 否則盡量使用合成/聚合.
濫用繼承會有如下問題,
1. 對象的繼承關系時編譯時就定義死的,無法運作時改變從父類繼承的實作, 缺乏靈活性
2. 子類和父類是緊耦合的,存在緊密的依賴關系, 父類的任何變化必然會導緻子類的變化.
3. 子類複用的問題, 當繼承下來的實作不适合新的問題時, 必須要修改父類.
4. 當然濫用繼承, 會導緻繼承層次迅速膨脹, 成為不可控制的龐然大物.
本文章摘自部落格園,原文釋出日期: 2013-02-05