軟件架構設計有七大原則,分別是:
1.開閉原則
2.依賴倒置原則
3.單一職責原則
4.接口隔離原則
5.迪米特法則(最小知道原則)
6.里氏替換原則
7.合成/聚合復用原則
下面分別具體說明:
1.開閉原則 :對擴展開放,對修改關閉
說的是,再設計一個模塊的時候,應當使這個模塊可以在不被修改的前提下被擴展.
換言之,應當可以在不必修改源代碼的情況下改變這個模塊的行為,在保持系統一定穩定性的基礎上,對系統進行擴展。
例如:一般軟件功能的升級就需要符合開閉原則,即不去修改原來的代碼,而是去增加新功能。
2.依賴倒置原則 :實現盡量依賴抽象,不依賴具體實現。
該原則有以下三點說明
1、高層模塊不應該依賴於底層模塊,兩者都應該依賴於抽象,
2、抽象不應該依賴於細節,即具體實現類。
3、細節應該依賴於抽象。
這樣帶來的好處,可以減少類與類之間的耦合性,提高系統的穩定性,提高代碼的可讀性和可維護性,並且可以降低修改程序所造成的的風險。
例如:我們在日常開發中拿到需求之后,一般都是面向接口編程,先設計出頂層,在細節的來設計代碼的結構。(以抽象為基准比以細節為基准搭建起來的架構要穩定的多)
3.單一職責原則 :對於一個類而言,應該僅存在一個可以引起類變化的原因。
從概念來說可能不大好理解,簡單的來講,就是我們平時在編程的時候,會在一個類上添加各種各樣的功能。當未來這些功能需要修改時,你不得不一遍又一遍的修改這個類,而且有可能導致其他的功能發生問題,維護起來很麻煩,很難復用,耦合性很大。
如果我們將這些功能分別用不同的類來實現,進行解耦,后期的需求變更和維護就會互不影響,能夠降低類的復雜度,提高可讀性,總的來講就是一個類、接口、方法只負責一項職責
4.接口隔離原則:客戶端不應該依賴它不需要的接口,類之間的依賴關系應該建立在最小的接口上。
這個原則指導我們在設計接口時應當注意一下幾點:
1、一個類對一類的依賴應該建立在最小的接口之上。
2、建立單一接口,不要建立功能繁多的總接口。
3、盡量細化接口,接口中的方法盡量少(不是越少越好,一定要適度)。
該原則符合高內聚低耦合的設計思想,可以使類具有很好的可讀性、可擴展性和可維護性。我們在設計接口的時候,應該多花時間思考,既要考慮到業務模型,還需要為以后可能發生的變更做出一些預判。
5.迪米特法則(最小知道原則):一個對象應該對其他對象保持最少的了解,盡量降低類與類之間的耦合。
由於每個類盡量減少對其他類的依賴,因此,很容易使得系統的功能模塊功能獨立,相互之間不存在(或很少有)依賴關系。迪米特法則不希望類之間建立直接的聯系。如果有真的需要建立聯系的,也希望能通過他的友元類來轉達。
迪米特原則主要強調只和朋友交流,不和陌生人說話。出現在成員變量、方法的輸入、輸出參數中的類都可以稱之為成員朋友類,而出現在方法體內部的類不屬於朋友類 。
6.里氏替換原則: 一個軟件實體如果適用一個父類的話,那一定是適用於其子類,所有引用父類的地方必須能透明地使用其子類的對象,子類對象能夠替換父類對象,而程序邏輯不變。
即任何基類可以出現的地方,子類一定可以出現。里氏代換原則是繼承復用的基石,只有當衍生類可以替換掉基類,軟件單位的功能不受影響時,基類才能被真正復用,而衍生類也能夠在積累的基礎上增加新的行為,里氏代換原則是對“開-閉”原則的補充。實現“開-閉”原則的關鍵步驟就是抽象化。在基類與子類的繼承關系就是抽象化的具體實現,所以里氏代換原則是對實現抽象化的具體步驟的規范。
當滿足繼承的時候,父類肯定存在非私有的成員,子類肯定是得到了父類的這些非私有成員(假設,父類的成員全部是私有的,那么子類沒辦法從父類繼承任何成員,也就不存在繼承的額概念了)。既然子類繼承了父類的這些非私有成員,那么父類對象也就可以在子類對象中調用這些非私有成員。所以,子類對象可以替換父類對象的位置。
在里氏帶環原則下,當需求有變化時,只需繼承,而別的東西不會改變。由於里氏代換原則才使得開放封閉稱為可能。這樣使得子類在父類無需修改就可以擴展。
我們總結一下:子類可以擴展父類的功能,但不能改變父類原有的功能。
1、子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法。
2、子類中可以增加自己特有的方法。
3、當子類的方法重載父類的方法時,方法的前置條件(即方法的輸入/入參)要比父類方法的輸入參數更寬松。
4、當子類的方法實現父類的方法時(重寫/重載或實現抽象方法),方法的后置條件(即方法的輸出/返回值)要比父類更嚴格或相等。
使用里氏替換原則有以下優點:
1、約束繼承泛濫,開閉原則的一種體現。
2、加強程序的健壯性,同時變更時也可以做到非常好的兼容性,提高程序的維護性、擴
展性。降低需求變更時引入的風險
7.合成/聚合復用原則:盡量使用對象組合(has-a)/聚合(contanis-a),而不是繼承關系達到軟件復用的目的。
換句話說,就是在一個新的對象里面使用一些已有的對象,使之成為新對象的一部分,新的對象通過這些對象的委派達到復用已有功能的目的。
該原則可以使系統更加靈活,降低類與類之間的耦合度,一個類的變化對其他類造成的影響相對較少。
總結:學習軟件設計原則,千萬不能形成強迫症。碰到業務復雜的場景,我們需要隨機應變。
在實際開發過程中,並不是一定要求所有代碼都遵循設計原則,我們要考慮人力、時間、成本、質量,不是刻意追求完美,
要在適當的場景遵循設計原則,體現的是一種平衡取舍,幫助我們設計出更加優雅的代碼結構