在軟件開發中,前人對軟件系統的設計和開發總結了一些原則和模式, 無論用什麼語言作開發,都將對咱們系統設計和開發提供指導意義。本文主要將總結這些常見的原則,和具體闡述意義。數據庫
面向對象的基本原則(solid)是五個,可是在常常被提到的除了這五個以外還有 迪米特法則和合成複用原則等, 因此在常見的文章中有表示寫六大或七大原則的; 除此以外我還將給出一些其它相關書籍和互聯網上出現的原則;編程
Single-Responsibility Principle, 一個類,最好只作一件事,只有一個引發它的變化。單一職責原則能夠看作是低耦合,高內聚在面向對象原則的引伸,將職責定義爲引發變化的緣由,以提升內聚性減小引發變化的緣由。設計模式
一個對象應該只包含單一的職責,而且該職責被完整地封裝在一個類中。(Every object should have a single responsibility, and that responsibility should be entirely encapsulated by the class.),即又定義有且僅有一個緣由使類變動。點擊這裏查看高可用架構設計9種方案詳解。緩存
注意:單一職責原則提出了一個編寫程序的標準,用「職責」或「變化緣由」來衡量接口或類設計得是否合理,可是「職責」和「變化緣由」都是沒有具體標準的,一個類到底要負責那些職責?這些職責怎麼細化?細化後是否都要有一個接口或類?這些都需從實際的狀況考慮。因項目而異,因環境而異。
Open - ClosedPrinciple ,OCP, 對擴展開放,對修改關閉(設計模式的核心原則)安全
一個軟件實體(如類、模塊和函數)應該對擴展開放,對修改關閉。意思是,在一個系統或者模塊中,對於擴展是開放的,對於修改是關閉的,一個 好的系統是在不修改源代碼的狀況下,能夠擴展你的功能。而實現開閉原則的關鍵就是抽象化。架構
Liskov Substitution Principle,LSP:任何基類能夠出現的地方,子類也能夠出現;這一思想表現爲對繼承機制的約束規範,只有子類可以替換其基類時,纔可以保證系統在運行期內識別子類,這是保證繼承複用的基礎。框架
第一種定義方式相對嚴格:若是對每個類型爲S的對象o1,都有類型爲T的對象o2,使得以T定義的全部程序P在全部的對象o1都代換成o2時,程序P的行爲沒有變化,那麼類型S是類型T的子類型。函數
第二種更容易理解的定義方式:全部引用基類(父類)的地方必須能透明地使用其子類的對象。即子類可以必須可以替換基類可以從出現的地方。子類也能在基類 的基礎上新增行爲。微服務
(里氏代換原則由2008年圖靈獎得主、美國第一位計算機科學女博士、麻省理工學院教授BarbaraLiskov和卡內基.梅隆大學Jeannette Wing教授於1994年提出。其原文以下:Let q(x) be a property provableabout objects x of type T. Then q(y) should be true for objects y of type Swhere S is a subtype of T. )學習
(Interface Segregation Principle,ISL):客戶端不該該依賴那些它不須要的接口。(這個法則與迪米特法則是相通的)
客戶端不該該依賴那些它不須要的接口。
另外一種定義方法:一旦一個接口太大,則須要將它分割成一些更細小的接口,使用該接口的客戶端僅需知道與之相關的方法便可。
注意,在該定義中的接口指的是所定義的方法。例如外面調用某個類的public方法。這個方法對外就是接口。
Dependency-Inversion Principle 要依賴抽象,而不要依賴具體的實現,具體而言就是高層模塊不依賴於底層模塊,兩者共同依賴於抽象。抽象不依賴於具體,具體依賴於抽象。
高層模塊不該該依賴低層模塊,它們都應該依賴抽象。抽象不該該依賴於細節,細節應該依賴於抽象。簡單的說,依賴倒置原則要求客戶端依賴於抽象耦合。原則表述:
(Composite/Aggregate ReusePrinciple ,CARP):要儘可能使用對象組合,而不是繼承關係達到軟件複用的目的
常常又叫作合成複用原則(Composite ReusePrinciple或CRP),儘可能使用對象組合,而不是繼承來達到複用的目的。
就是在一個新的對象裏面使用一些已有的對象,使之成爲新對象的一部分;新對象經過向這些對象的委派達到複用已有功能的目的。簡而言之,要儘可能使用合成/聚合,儘可能不要使用繼承。
繼承複用:實現簡單,易於擴展。破壞系統的封裝性;從基類繼承而來的實現是靜態的,不可能在運行時發生改變,沒有足夠的靈活性;只能在有限的環境中使用。(「白箱」複用)
組合/聚合複用:耦合度相對較低,選擇性地調用成員對象的操做;能夠在運行時動態進行。(「黑箱」複用)
注意:聚合和組合的區別是什麼?
合成(組合):表示一個總體與部分的關係,指一個依託總體而存在的關係(總體與部分不能夠分開);好比眼睛和嘴對於頭來講就是組合關係,沒有了頭就沒有眼睛和嘴,它們是不可分割的。在UML中,組合關係用帶實心菱形的直線表示。
聚合:聚合是比合成關係的一種更強的依賴關係,也表示總體與部分的關係(總體與部分能夠分開);好比螺絲和汽車玩具的關係,螺絲脫離玩具依然能夠用在其它設備之上。在UML中,聚合關係用帶空心菱形的直線表示。
(Law of Demeter,LoD:系統中的類,儘可能不要與其餘類互相做用,減小類之間的耦合度
又叫最少知識原則(Least Knowledge Principle或簡寫爲LKP)幾種形式定義:
不要和「陌生人」說話。英文定義爲:Don't talk to strangers.
只與你的直接朋友通訊。英文定義爲:Talk only to your immediate friends.
每個軟件單位對其餘的單位都只有最少的知識,並且侷限於那些與本單位密切相關的軟件單位。
簡單地說,也就是,一個對象應當對其它對象有儘量少的瞭解。一個類應該對本身須要耦合或調用的類知道得最少,你(被耦合或調用的類)的內部是如何複雜都和我不要緊,那是你的事情,我就知道你提供的public方法,我就調用這麼多,其餘的一律不關心。
在迪米特法則中,對於一個對象,其朋友包括如下幾類: (1) 當前對象自己(this); (2) 以參數形式傳入到當前對象方法中的對象; (3) 當前對象的成員對象; (4) 若是當前對象的成員對象是一個集合,那麼集合中的元素也都是朋友;(5) 當前對象所建立的對象。
任何一個對象,若是知足上面的條件之一,就是當前對象的「朋友」,不然就是「陌生人」。
在狹義的迪米特法則中,若是兩個類之間沒必要彼此直接通訊,那麼這兩個類就不該當發生直接的相互做用,若是其中的一個類須要調用另外一個類的某一個方法的話,能夠經過第三者轉發這個調用。
能夠下降類之間的耦合,可是會在系統中增長大量的小方法並散落在系統的各個角落,它可使一個系統的局部設計簡化,由於每個局部都不會和遠距離的對象有直接的關聯,可是也會形成系統的不一樣模塊之間的通訊效率下降,使得系統的不一樣模塊之間不容易協調。點擊這裏查看高可用架構設計9種方案詳解。
指對對象之間的信息流量、流向以及信息的影響的控制,主要是對信息隱藏的控制。信息的隱藏可使各個子系統之間脫耦,從而容許它們獨立地被開發、優化、使用和修改,同時能夠促進軟件的複用,因爲每個模塊都不依賴於其餘模塊而存在,所以每個模塊均可以獨立地在其餘的地方使用。一個系統的規模越大,信息的隱藏就越重要,而信息隱藏的重要性也就越明顯。
封裝變化
少用繼承 多用組合
針對接口編程 不針對實現編程
爲交互對象之間的鬆耦合設計而努力
類應該對擴展開發 對修改封閉(開閉OCP原則)
依賴抽象,不要依賴於具體類(依賴倒置DIP原則)
密友原則:只和朋友交談(最少知識原則,迪米特法則)
說明:一個對象應當對其餘對象有儘量少的瞭解,將方法調用保持在界限內,只調用屬於如下範圍的方法: 該對象自己(本地方法)對象的組件 被看成方法參數傳進來的對象 此方法建立或實例化的任何對象
別找我(調用我) 我會找你(調用你)(好萊塢原則)
一個類只有一個引發它變化的緣由(單一職責SRP原則)
嚴格定義:若是對每個類型爲S的對象o1,都有類型爲T的對象o2,使得以T定義的全部程序P在全部的對象用o1替換o2時,程序P的行爲沒有變化,那麼類型S是類型T的子類型。
通俗表述:全部引用基類(父類)的地方必須能透明地使用其子類的對象。也就是說子類能夠擴展父類的功能,但不能改變父類原有的功能。它包含如下4層含義:
子類能夠實現父類的抽象方法,但不能覆蓋父類的非抽象方法。
子類中能夠增長本身特有的方法。
當子類的方法重載父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數更寬鬆。
當子類的方法實現父類的抽象方法時,方法的後置條件(即方法的返回值)要比父類更嚴格。
迪米特法則建議「只和朋友說話,不要陌生人說話」,以此來減小類之間的耦合。
開閉原則要求你的代碼對擴展開放,對修改關閉。這個意思就是說,若是你想增長一個新的功能,你能夠很容易的在不改變已測試過的代碼的前提下增長新的代碼。有好幾個設計模式是基於開閉原則的,如策略模式,若是你須要一個新的策略,只須要實現接口,增長配置,不須要改變核心邏輯。一個正在工做的例子是 Collections.sort() 方法,這就是基於策略模式,遵循開閉原則的,你不需爲新的對象修改 sort() 方法,你須要作的僅僅是實現你本身的 Comparator 接口。
享元模式經過共享對象來避免建立太多的對象。爲了使用享元模式,你須要確保你的對象是不可變的,這樣你才能安全的共享。JDK 中 String 池、Integer 池以及 Long 池都是很好的使用了享元模式的例子。
歡迎你們加入粉絲交流羣: 963944895,免費分享Spring框架、Mybatis框架SpringBoot框架、SpringMVC框架、SpringCloud微服務、Dubbo框架、Redis緩存、RabbitMq消息、JVM調優、Tomcat容器、MySQL數據庫教學視頻及架構學習思惟導圖
既然看到這裏了,以爲筆者寫的還不錯的就點個贊,加個關注唄!點關注,不迷路,持續更新!!!