概述:
OOP的方法論(高內聚、低耦合、易複用、易擴展、易維護):
1. 代碼重用(一般用繼承和聚合實現)
2. 低耦合(模塊與模塊之間,類與類之間依賴程度低)
3. 高內聚(模塊或類內部依賴程度高,負責處理相關的工做,避免「狗拿耗子」)
4. 易擴充(在不改變原有代碼,或改變很小的狀況下增長功能)
5. 易維護(代碼結構清晰,容易管理和修改代碼)java
一 OCP(Open-Closed Principle) 開放-封閉原則
軟件實體應該擴展開放、修改封閉:
1. 「對於擴展是開放的」 (Open for extension)。這意味着模塊的行爲是能夠擴展的,當應用的需求改變時,咱們能夠對模塊進行擴展,使其具備知足那些改變的新行爲,換句話說,咱們能夠改變模塊的功能。
2. 「對於更改是封閉的」 (Closed for modification)。對模塊行爲進行擴展時,沒必要改動模塊的源代碼或者二進制代碼,模塊的二進制可執行版本,不管是可連接的庫、DLL或JAVA 的.jar文件,都無需改動。
實現:合理劃分構件,一種可變性不該當散落在代碼的不少角落裏,而應當被封裝到一個對象裏;一種可變性不該當和另外一個可變性混合在一塊兒。
二 DIP(Dependency-Inversion Principles)依賴倒置原則
在傳統的結構化編程中,最上層的模塊一般都要依賴下面的子模塊來實現,也稱爲高層依賴低層! DIP原則就是要逆轉這種依賴關係,讓高層模塊不要依賴低層模塊。
第1點:高層模塊不依賴底層模塊,二者都依賴抽象。
第2點:抽象不該該依賴於細節,細節應該依賴於抽象。
每一個較高層次都爲它所須要的服務聲明一個抽象接口,較低的層次實現這些抽象接口,每一個高層類都經過該抽象接口使用下一層的服務,接口屬於高層,低層要實現高層的接口,所以如今是低層依賴於高層是依賴關係倒置和接口全部權的倒置。
實現:應該經過抽象耦合的方式,使具體類最大可能的僅和其抽象類(接口)發生耦合;程式在須要引用一個對象時,應當儘量的使用抽象類型做爲變量的靜態類型,這就是針對接口編程的含義。
三 LSP(Liskov Substitution Principle) 替換原則
繼承思想的基礎。「只有當衍生類可以替換掉基類,軟件單位的功能不會受到影響時,基類才真正被複用,而衍生類也纔可以在基類的基礎上增長新的行爲。
四 ISP(Interface Insolation Principle)接口隔離原則
接口功能單一,避免接口污染。
一個接口表明一個角色,不該當將不一樣的角色都交給一個接口。沒有關係的接口合併在一塊兒,造成一個臃腫的大接口,這是對角色和接口的污染----角色隔離原則。
將接口理解成爲俠義的java接口,這樣一來,接口隔離原則講的就是爲同一個角色提供寬、窄不一樣的接口,以對付不一樣的客戶端。這種辦法在服務行業中叫作定製服務---定製服務。
「不該該強迫客戶依賴於它們不用的方法。接口屬於客戶,不屬於它所在的類層次結構。」這個說得很明白了,再通俗點說,不要強迫客戶使用它們不用的方法,若是強迫用戶使用它們不使用的方法,那麼這些客戶就會面臨因爲這些不使用的方法的改變所帶來的改變。
實現:一個類對另一個類的依賴性應當是創建在最小的接口上的。使用多個專門的接口比使用單一的總接口要好。
(動機:當咱們設計應用程序的時候,若是一個模塊包含多個子模塊,那麼咱們應該當心對該模塊作出抽象。設想該模塊由一個類實現,咱們能夠把系統抽象成一個接口。但 是當咱們想要添加一個新的模塊擴展程序時,若是要添加的模塊只包含原系統中的一些子模塊,那麼就會強迫咱們實現接口中的全部方法,而且還要編寫一些啞方 法。這樣的接口被稱爲胖接口或者叫被污染的接口,使用這樣的接口將會給系統引入一些不正確的行爲。)
五 SRP(Single Resposibility Principle) 單一職責原則
就一個類而言,應該僅有一個引發他變化的緣由。 假如一個類的職責過多,就等於把這些職責耦合在一塊兒,一個職責的變化可能會抑止這個類完成其餘職責的能力。
單一職責原則的好處:
第1、有助於咱們分析和編碼的思路的清晰。(當你的代碼裏有了三層或以上的if語句或for語句的嵌套的時候,你不要跟我說,你已經把問題分析得很清楚了。多層嵌套的if或for語句只能說明你尚未把問題分析清楚。)
第2、使咱們的編碼、測試和維護變得簡單。
第3、將一個個複雜的問題簡單化之後,易於代碼的重用。(當你的代碼的多個功能攪和在一塊兒的時候,你是沒辦法考慮代碼的重用的,由於你的每一處代碼都有不一樣。)
第4、易於系統的擴展
與接口隔離原則(ISP)的比較:
相同點:接口儘可能細化,同時接口中的方法儘可能少。
不一樣點:審視角度是不相同的,單一職責要求的是類和接口職責單一,注重的是職責,這是業務邏輯上的劃分,而接口隔離原則要求接口的方法儘可能少。(例如:一個接口的職責可能包含10個方法,這10個方法都放在一個接口中,而且提供給多個模塊訪問,各個模塊按照規定的權限來訪問,在系統外經過文檔約束「不使用的方法不要訪問」,按照單一職責原則是容許的,按照接口隔離原則是不容許的,由於它要求「儘可能使用多個專門的接口」。專門的接口指什麼?就是指提供給每一個模塊都應該是單一接口,提供給幾個模塊就應該有幾個接口,而不是創建一個龐大的臃腫的接口,容納全部的客戶端訪問。)
六 LoD (Law of Demeter)迪米特法則
即最少知識原則。一個對象應當對其餘對象有儘量少的瞭解。只和最直接的類交互,對第三方能夠經過轉達交互,從而減小對象間的耦合性。編程
七 CARP(Composite/Aggregate Reuse Principle)合成/聚合複用原則
就是在一個新的對象裏面使用一些已有的對象,使之成爲新對象的一部分;新的對象經過向這些對象的委派達到複用已有功能的目的。簡而言之就是:要儘可能使用合成/聚合,儘可能不要使用繼承。
聚合:用來表示「擁有」關係或者總體和部分的關係。
合成:用來表示一種強得多的「擁有」關係。在一個合成裏,部分和總體的生命週期是同樣的。一個合成的新對象徹底擁有對其組成部分的支配權,包括它們的建立和泯滅等。
合成/聚合複用:
優勢:
* 新對象存取成分對象的惟一方法是經過成分對象的接口。
* 這種複用是黑箱複用,由於成分對象的內部細節是新對象所看不見的。
* 這種複用支持包裝。
* 這種複用所需的依賴較少。
* 每個新的類能夠將焦點集中在一個任務上。
* 這種複用能夠在運行時間內動態進行,新對象能夠動態的引用與成分對象類型相同的對象。
缺點:
* 系統中會有比較多的對象須要管理。
經過繼承的複用:
合成/聚合做爲複用手段能夠應用到幾乎任何環境中去,而繼承只能在有限的環境中使用。儘管繼承是一種很是重要的複用手段,但應當首先考慮合成/聚合,而不是繼承。
優勢:
* 新的實現較爲容易,由於超類的大部分功能能夠經過繼承的關係自動進入子類。
* 修改和擴展繼承而來的實現較爲容易。
缺點:
* 繼承複用破壞包裝,由於繼承將超類的實現細節暴露給子類。因爲超類的內部細節經常是對於子類透明的,因此這種複用是透明的複用,又稱「白箱」複用。
* 若是超類發生改變,那麼子類的實現也不得不發生改變。
* 從超類繼承而來的實現是靜態的,不可能在運行時間內發生改變,沒有足夠的靈活性。
在對違反里氏代換原則的設計進行重構時,有兩種方法:一是加入一個抽象超類;二是將繼承改成合成/聚合的關係。
「Is-A」表明一個類是另一個類的一種,「Has-A」表明一個類是另外一個類的一個角色,而不是另外一個類的特殊種類。對於"Is-A"應該考慮使用繼承,而"Has-A"使用合成/聚合。設計模式
備註:ide
設計模式和設計原則的關係就像是三十六計與孫子兵法的關係。前者是具體的人們總結的經驗,這些經驗體現着原則;後者是更通常的更抽象的更廣泛的指導原則。 抓住可維護性和可複用性這兩隻同時在奔跑的兔子的方法是:支持可維護性的複用(在保持甚至提升系統的可維護性的同時,實現系統的複用)。測試