天天看點

Design Pattern - 7原則

很多程式員用面向對象語言寫了多年的代碼, 仍然不知道設計模式為何物, 這不奇怪, 設計模式并不是非有不可,可是它能讓代碼變的更美好。 

程式員大可悶頭堆代碼, 複制粘貼, 然後不斷的感慨代碼難以維護, 難以複用, 難以擴充, 而繼續不思進取。 

當然也可以選折不斷去追求更美好, 更合理的代碼, 把自己從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

繼續閱讀