這些原則不僅僅侷限於設計模式中,適用於任何編碼階段。
工廠模式的三類中就很好的考慮了開閉原則、依賴倒置原則、迪米特原則。
六大原則:單一職責原則(Single Responsibility Principle)
里氏替換原則(Liskov Substitution Principle)
依賴倒置原則(Dependence Inversion Principle)
接口隔離原則(Interface Segregation Principle)——開閉原則的基礎
迪米特原則(Demeter Principle)
開閉原則(Open Close Principle)——基石
1、單一職責原則
定義:一個類只負責一個功能領域的職責,即有且僅有一原因引起類的變化(方法、接口也一樣)
解釋:軟件系統中,一個類承擔的職責越多,它被複用的可能性就越小,耦合度就越高
核心優點:降低耦合度
1) 降低了類的複雜度。一個類只負責一項職責比負責多項職責要簡單得多。
2) 提高了代碼的可讀性。一個類簡單了,可讀性自然就提高了。
3) 提高了系統的可維護性。代碼的可讀性高了,並且修改一項職責對其他職責影響降低了,可維護性自然就提高了。
4) 變更引起的風險變低了。單一職責最大的優點就是修改一個功能,對其他功能的影響顯著降低。
實際編程中要綜合考慮類級別、方法級別、接口級別的單一職責原則,有時需要違背類級別的SRP而確保方法級別的SRP,是開銷降低。
2、里氏替換原則
定義:所有引用基類(父類)的地方必須能透明地使用其子類的對象
里氏替換原則前提:使用繼承(類B繼承類A),除添加新的方法完成新增功能外,儘量不要重寫父類A的方法,也儘量不要重載父類A的方法
如果非要重寫父類的方法,比較通用的做法是:原來的父類和子類都繼承一個更通俗的基類,原有的繼承關係去掉,採用依賴、聚合,組合等關係代替。
繼承的優勢:簡化人們對事物的認識,清晰體現類之間的層次關係;提高代碼的複用性;實現多態;減少程序複雜度
繼承的劣勢:程序的可移植性降低;增加了對象間的耦合性;給程序帶來侵入性
3、依賴倒置原則
定義:高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。
問題由來:類A直接依賴類B,假如要將類A改爲依賴類C,則必須通過修改類A的代碼來達成。這種場景下,類A一般是高層模塊,負責複雜的業務邏輯;類B和類C是低層模塊,負責基本的原子操作;假如修改類A,會給程序帶來不必要的風險。
解決方案:將類A修改爲依賴接口I,類B和類C各自實現接口I,類A通過接口I間接與類B或者類C發生聯繫,則會大大降低修改類A的機率。
依賴的三種方法:
構造函數傳遞依賴對象
setter函數傳遞依賴對象
接口的方法中傳遞依賴對象
依賴倒置原則基於這樣一個事實:相對於細節的多變性,抽象的東西要穩定的多。以抽象爲基礎搭建起來的架構比以細節爲基礎搭建起來的架構要穩定的多。在java中,抽象指的是接口或者抽象類,細節就是具體的實現類,使用接口或者抽象類的目的是制定好規範和契約,而不去涉及任何具體的操作,把展現細節的任務交給他們的實現類去完成。
依賴倒置原則的核心思想是面向接口編程,我們依舊用一個例子來說明面向接口編程比相對於面向實現編程好在什麼地方。
M依賴B,現在要使M依賴N,高層模塊M就需要變動(不好)
解決方案:面向接口/抽象類
4、接口隔離原則
定義:客戶端不應該依賴它不需要的接口;一個類對另一個類的依賴應該建立在最小的接口上。
概括 : 建立單一接口,不要建立臃腫龐大的接口,也就是接口儘量細化,接口中的方法儘量少
這個是開閉原則的基礎,具體內容:針對接口編程,依賴於抽象而不依賴於具體。
比如我們設計一個手機的接口時,就要手機哪些行爲是必須的,要讓這個接口儘量的小
public interface Mobile {
public void call();//手機可以打電話
public void sendMessage();//手機可以發短信
public void playBird();//手機可以玩憤怒的小鳥? ----這條顯然不是必須的,還可以拆
}
5、迪米特原則
定義:一個類應該儘量不要知道其他類太多的東西,不要和陌生的類有太多接觸(只與直接朋友通信)。
朋友類:朋友類也可以這樣定義:出現在成員變量,方法的輸入輸出參數中的類,稱爲朋友類。
6、開閉原則
定義 : 一個軟件實體如類,模塊和函數應該對擴展開放,對修改關閉
開閉原則無非就是想表達這樣一層意思:用抽象構建框架,用實現擴展細節。因爲抽象靈活性好,適應性廣,只要抽象的合理,可以基本保持軟件架構的穩定。而軟件中易變的細節,我們用從抽象派生的實現類來進行擴展,當軟件需要發生變化時,我們只需要根據需求重新派生一個實現類來擴展就可以了。當然前提是我們的抽象要合理,要對需求的變更有前瞻性和預見性才行。