設計原則是基本的工具應用這些規則可使代碼更加靈活更容易維護更容易擴展基本原則封裝變化 Encapsulate what varies 面向接口變成而不是實現 Code to an interface rather than to an implementation 優先使用組合而非繼承 Favor Composition Over Inheritan
什麼是設計原則?
設計原則是基本的工具應用這些規則可以使你的代碼更加靈活更容易維護更容易擴展
基本原則
封裝變化Encapsulate what varies
面向接口變成而不是實現 Code to an interface rather than to an implementation
優先使用組合而非繼承 Favor Composition Over Inheritance
SRP: The single responsibility principle 單一職責
系統中的每一個對象都應該只有一個單獨的職責而所有對象所關注的就是自身職責的完成
Every object in your system should have a single responsibility and all the object s services should be focused on carrying out that single responsibility
每一個職責都是一個設計的變因需求變化的時候需求變化反映為類職責的變化當你系統裡面的對象都只有一個變化的原因的時候你就已經很好的遵循了SRP原則
如果一個類承擔的職責過多就等於把這些職責耦合在了一起一個職責的變化就可能削弱或者抑制這個類其它職責的能力這種設計會導致脆弱的設計當變化發生的時候設計會遭到意想不到的破壞
SRP 讓這個系統更容易管理維護因為不是所有的問題都攪在一起
內聚Cohesion 其實是SRP原則的另外一個名字你寫了高內聚的軟件其實就是說你很好的應用了SRP原則
怎麼判斷一個職責是不是一個對象的呢?你試著讓這個對象自己來完成這個職責比如書自己閱讀內容閱讀的職責顯然不是書自己的
僅當變化發生時變化的軸線才具有實際的意義如果沒有征兆那麼應用SRP或者任何其它的原則都是不明智的
DRY : Dont repeat yourself Principle
通過抽取公共部分放置在一個地方避免代碼重復
Avoid duplicate code by abstracting out things that are common and placing those thing in a single location
DRY 很簡單但卻是確保我們代碼容易維護和復用的關鍵
你盡力避免重復代碼候實際上在做一件什麼事情呢?是在確保每一個需求和功能在你的系統中只實現一次否則就存在浪費!系統用例不存在交集所以我們的代碼更不應該重復從這個角度看DRY可就不只是在說代碼了
DRY 關注的是系統內的信息和行為都放在一個單一的明顯的位置就像你可以猜到正則表達式中的位置一樣因為合理所以可以猜到
DRY 原則如何對系統職能進行良好的分割!職責清晰的界限一定程度上保證了代碼的單一性
OCP : OpenClose Principle開閉原則
類應該對修改關閉對擴展打開
Classes should be open for extension and closed for modification
OCP 關注的是靈活性改動是通過增加代碼進行的而不是改動現有的代碼
OCP的應用限定在可能會發生的變化上通過創建抽象來隔離以後發生的同類變化
OCP原則傳遞出來這樣一個思想一旦你寫出來了可以工作的代碼就要努力保證這段代碼一直可以工作這可以說是一個底線稍微提高一點要求一旦我們的代碼質量到了一個水平我們要盡最大努力保證代碼質量不回退這樣的要求使我們面對一個問題的時候不會使用湊活的方法來解決或者說是放任自流的方式來解決一個問題比如代碼添加了無數對特定數據的處理特化的代碼越來越多代碼意圖開始含混不清開始退化
OCP 背後的機制封裝和抽象封閉是建立在抽象基礎上的使用抽象獲得顯示的封閉繼承是OCP最簡單的例子除了子類化和方法重載我們還有一些更優雅的方法來實現比如組合
怎樣在不改變源代碼(關閉修改)的情況下更改它的行為呢?答案就是抽象OCP背後的機制就是抽象和多態
沒有一個可以適應所有情況的貼切的模型!一定會有變化不可能完全封閉對程序中的每一個部分都肆意的抽象不是一個好主意正確的做法是開發人員僅僅對頻繁變化的部分做出抽象拒絕不成熟的抽象和抽象本身一樣重要
OCP是OOD很多說法的核心如果這個原則有效應用我們就可以獲更強的可維護性 可重用 靈活性 健壯性 LSP是OCP成為可能的主要原則之一
LSP: The Liskov substitution principle
子類必須能夠替換基類
Subtypes must be substitutable for their base types
LSP關注的是怎樣良好的使用繼承
必須要清楚是使用一個Method還是要擴展它但是絕對不是改變它
LSP清晰的指出OOD的ISA關系是就行為方式而言行為方式是可以進行合理假設的是客戶程序所依賴的
LSP讓我們得出一個重要的結論一個模型如果孤立的看並不具有真正意義的有效性模型的有效性只能通過它的客戶程序來表現必須根據設計的使用者做出的合理假設來審視它而假設是難以預測的直到設計臭味出現的時候才處理它們
對於LSP的違反也潛在的違反了OCP
DIP依賴倒置原則
高層模塊不應該依賴於底層模塊 二者都應該依賴於抽象
抽象不應該依賴於細節 細節應該依賴於抽象
什麼是高層模塊?高層模塊包含了應用程序中重要的策略選擇和業務模型這些高層模塊使其所在的應用程序區別於其它
如果高層模塊依賴於底層模塊那麼在不同的上下文中重用高層模塊就會變得十分困難然而如果高層模塊獨立於底層模塊那麼高層模塊就可以非常容易的被重用該原則就是框架設計的核心原則
這裡的倒置不僅僅是依賴關系的倒置也是接口所有權的倒置應用了DIP我們會發現往往是客戶擁有抽象的接口而服務者從這些抽象接口派生
這就是著名的Hollywood原則:Dont call us well call you底層模塊實現了在高層模塊聲明並被高層模塊調用的接口
通過倒置我們創建了更靈活 更持久更容易改變的結構
DIP的簡單的啟發規則依賴於抽象這是一個簡單的陳述該規則建議不應該依賴於具體的類也就是說程序匯總所有的依賴都應該種植於抽象類或者接口
如果一個類很穩定那麼依賴於它不會造成傷害然而我們自己的具體類大多是不穩定的通過把他們隱藏在抽象接口後面可以隔離不穩定性
依賴倒置可以應用於任何存在一個類向另一個類發送消息的地方
依賴倒置原則是實現許多面向對象技術多宣稱的好處的基本底層機制是面向對象的標志所在
ISP:接口隔離原則
不應該強迫客戶程序依賴它們不需要的使用的方法
接口不是高內聚的一個接口可以分成N組方法那麼這個接口就需要使用ISP處理一下
接口的劃分是由使用它的客戶程序決定的客戶程序是分離的接口也應該是分離的
一個接口中包含太多行為時候導致它們的客戶程序之間產生不正常的依賴關系我們要做的就是分離接口實現解耦
應用了ISP之後客戶程序看到的是多個內聚的接口
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26036.html