寫在前面
- 軟件設(shè)計(jì)七大原則
- 開閉原則
- 里氏替換原則
- 依賴倒置原則
- 單一職責(zé)原則
- 接口隔離原則
- 迪米特法則
- 合成復(fù)用原則
- 創(chuàng)建型模式
- 單例(Singleton)模式
- 原型(Prototype)模式
- 簡(jiǎn)單工廠(Simple Factory)模式
- 工廠方法(Factory Method)模式
- 抽象工廠(Abstract Factory)模式
- 建造者(Builder)模式
- 結(jié)構(gòu)型模式
- 代理(Proxy)模式
- 適配器(Adapter)模式
- 橋接(Bridge)模式
- 裝飾(Decorator)模式
- 外觀(Facade)模式
- 享元(Flyweight)模式
- 組合(Composite)模式
- 行為型模式
- 模板方法(Template Method)模式
- 策略(Strategy)模式
- 命令(Command)模式
- 職責(zé)鏈(Chain of Responsibility)模式
- 狀態(tài)(State)模式
- 觀察者(Observer)模式
- 中介者(Mediator)模式
- 迭代器(Iterator)模式
- 訪問者(Visitor)模式
- 備忘錄(Memento)模式
- 解釋器(Interpreter)模式
本系列共四篇筆記分別如下:
- 設(shè)計(jì)模式-01篇-軟件設(shè)計(jì)七大原則
- 設(shè)計(jì)模式-02篇-創(chuàng)建型模式
- 設(shè)計(jì)模式-03篇-結(jié)構(gòu)型模式
- 設(shè)計(jì)模式-04篇-行為型模式
開閉原則
定義: 軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。
作用:
- 對(duì)軟件測(cè)試的影響:軟件遵守開閉原則的話,軟件測(cè)試時(shí)只需要對(duì)擴(kuò)展的代碼進(jìn)行測(cè)試就可以了,因?yàn)樵械臏y(cè)試代碼仍然能夠正常運(yùn)行。
- 可以提高代碼的可復(fù)用性:粒度越小,被復(fù)用的可能性就越大;在面向?qū)ο蟮某绦蛟O(shè)計(jì)中,根據(jù)原子和抽象編程可以提高代碼的可復(fù)用性。
- 可以提高軟件的可維護(hù)性:遵守開閉原則的軟件,其穩(wěn)定性高和延續(xù)性強(qiáng),從而易于擴(kuò)展和維護(hù)。
實(shí)現(xiàn):
可以通過“抽象約束、封裝變化”來(lái)實(shí)現(xiàn)開閉原則,即通過接口或者抽象類為軟件實(shí)體定義一個(gè)相對(duì)穩(wěn)定的抽象層,而將相同的可變因素封裝在相同的具體實(shí)現(xiàn)類中。
里氏替換原則
定義: 繼承必須確保超類所擁有的性質(zhì)在子類中仍然成立。(通俗來(lái)講:子類可以擴(kuò)展父類的功能,但不能改變父類原有的功能。也可以說(shuō):子類繼承父類時(shí),除添加新的方法完成新增功能外,盡量不要重寫父類的方法。)
作用:
- 里氏替換原則是實(shí)現(xiàn)開閉原則的重要方式之一。
- 它克服了繼承中重寫父類造成的可復(fù)用性變差的缺點(diǎn)。
- 它是動(dòng)作正確性的保證。即類的擴(kuò)展不會(huì)給已有的系統(tǒng)引入新的錯(cuò)誤,降低了代碼出錯(cuò)的可能性。
- 加強(qiáng)程序的健壯性,同時(shí)變更時(shí)可以做到非常好的兼容性,提高程序的維護(hù)性、可擴(kuò)展性,降低需求變更時(shí)引入的風(fēng)險(xiǎn)。
實(shí)現(xiàn):
- 子類可以實(shí)現(xiàn)父類的抽象方法,但不能覆蓋父類的非抽象方法
- 子類中可以增加自己特有的方法
- 當(dāng)子類的方法重載父類的方法時(shí),方法的前置條件(即方法的輸入?yún)?shù))要比父類的方法更寬松
- 當(dāng)子類的方法實(shí)現(xiàn)父類的方法時(shí)(重寫/重載或?qū)崿F(xiàn)抽象方法),方法的后置條件(即方法的的輸出/返回值)要比父類的方法更嚴(yán)格或相等
依賴倒置原則
定義: 高層模塊不應(yīng)該依賴低層模塊,兩者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴抽象。其核心思想是:要面向接口編程,不要面向?qū)崿F(xiàn)編程。
作用:
- 依賴倒置原則可以降低類間的耦合性。
- 依賴倒置原則可以提高系統(tǒng)的穩(wěn)定性。
- 依賴倒置原則可以減少并行開發(fā)引起的風(fēng)險(xiǎn)。
- 依賴倒置原則可以提高代碼的可讀性和可維護(hù)性。
實(shí)現(xiàn):
- 每個(gè)類盡量提供接口或抽象類,或者兩者都具備。
- 變量的聲明類型盡量是接口或者是抽象類。
- 任何類都不應(yīng)該從具體類派生。
- 使用繼承時(shí)盡量遵循里氏替換原則。
單一職責(zé)原則
定義: 這里的職責(zé)是指類變化的原因,單一職責(zé)原則規(guī)定一個(gè)類應(yīng)該有且僅有一個(gè)引起它變化的原因,否則類應(yīng)該被拆分。
作用:
單一職責(zé)原則的核心就是控制類的粒度大小、將對(duì)象解耦、提高其內(nèi)聚性。如果遵循單一職責(zé)原則將有以下優(yōu)點(diǎn)。
- 降低類的復(fù)雜度。一個(gè)類只負(fù)責(zé)一項(xiàng)職責(zé),其邏輯肯定要比負(fù)責(zé)多項(xiàng)職責(zé)簡(jiǎn)單得多。
- 提高類的可讀性。復(fù)雜性降低,自然其可讀性會(huì)提高。
- 提高系統(tǒng)的可維護(hù)性??勺x性提高,那自然更容易維護(hù)了。
變更引起的風(fēng)險(xiǎn)降低。變更是必然的,如果單一職責(zé)原則遵守得好,當(dāng)修改一個(gè)功能時(shí),可以顯著降低對(duì)其他功能的影響。
實(shí)現(xiàn):
單一職責(zé)原則是最簡(jiǎn)單但又最難運(yùn)用的原則,需要設(shè)計(jì)人員發(fā)現(xiàn)類的不同職責(zé)并將其分離,再封裝到不同的類或模塊中。而發(fā)現(xiàn)類的多重職責(zé)需要設(shè)計(jì)人員具有較強(qiáng)的分析設(shè)計(jì)能力和相關(guān)重構(gòu)經(jīng)驗(yàn)。
接口隔離原則
定義: 客戶端不應(yīng)該被迫依賴于它不使用的方法 。該原則還有另外一個(gè)定義:一個(gè)類對(duì)另一個(gè)類的依賴應(yīng)該建立在最小的接口上。
以上兩個(gè)定義的含義是:要為各個(gè)類建立它們需要的專用接口,而不要試圖去建立一個(gè)很龐大的接口供所有依賴它的類去調(diào)用。
作用:
- 將臃腫龐大的接口分解為多個(gè)粒度小的接口,可以預(yù)防外來(lái)變更的擴(kuò)散,提高系統(tǒng)的靈活性和可維護(hù)性。
- 接口隔離提高了系統(tǒng)的內(nèi)聚性,減少了對(duì)外交互,降低了系統(tǒng)的耦合性。
- 如果接口的粒度大小定義合理,能夠保證系統(tǒng)的穩(wěn)定性;但是,如果定義過小,則會(huì)造成接口數(shù)量過多,使設(shè)計(jì)復(fù)雜化;如果定義太大,靈活性降低,無(wú)法提供定制服務(wù),給整體項(xiàng)目帶來(lái)無(wú)法預(yù)料的風(fēng)險(xiǎn)。
- 使用多個(gè)專門的接口還能夠體現(xiàn)對(duì)象的層次,因?yàn)榭梢酝ㄟ^接口的繼承,實(shí)現(xiàn)對(duì)總接口的定義。
- 能減少項(xiàng)目工程中的代碼冗余。過大的大接口里面通常放置許多不用的方法,當(dāng)實(shí)現(xiàn)這個(gè)接口的時(shí)候,被迫設(shè)計(jì)冗余的代碼。
實(shí)現(xiàn):
- 接口盡量小,但是要有限度。一個(gè)接口只服務(wù)于一個(gè)子模塊或業(yè)務(wù)邏輯。
- 為依賴接口的類定制服務(wù)。只提供調(diào)用者需要的方法,屏蔽不需要的方法。
- 了解環(huán)境,拒絕盲從。每個(gè)項(xiàng)目或產(chǎn)品都有選定的環(huán)境因素,環(huán)境不同,接口拆分的標(biāo)準(zhǔn)就不同深入了解業(yè)務(wù)邏輯。
- 提高內(nèi)聚,減少對(duì)外交互。使接口用最少的方法去完成最多的事情。
迪米特法則
定義: 又叫作最少知識(shí)原則。只與你的直接朋友交談,不跟“陌生人”說(shuō)話。其含義是:如果兩個(gè)軟件實(shí)體無(wú)須直接通信,那么就不應(yīng)當(dāng)發(fā)生直接的相互調(diào)用,可以通過第三方轉(zhuǎn)發(fā)該調(diào)用。其目的是降低類之間的耦合度,提高模塊的相對(duì)獨(dú)立性。
作用:
- 降低了類之間的耦合度,提高了模塊的相對(duì)獨(dú)立性。
- 由于親合度降低,從而提高了類的可復(fù)用率和系統(tǒng)的擴(kuò)展性。
但是,過度使用迪米特法則會(huì)使系統(tǒng)產(chǎn)生大量的中介類,從而增加系統(tǒng)的復(fù)雜性,使模塊之間的通信效率降低。所以,在釆用迪米特法則時(shí)需要反復(fù)權(quán)衡,確保高內(nèi)聚和低耦合的同時(shí),保證系統(tǒng)的結(jié)構(gòu)清晰。
實(shí)現(xiàn):
- 在類的劃分上,應(yīng)該創(chuàng)建弱耦合的類。類與類之間的耦合越弱,就越有利于實(shí)現(xiàn)可復(fù)用的目標(biāo)。
- 在類的結(jié)構(gòu)設(shè)計(jì)上,盡量降低類成員的訪問權(quán)限。
- 在類的設(shè)計(jì)上,優(yōu)先考慮將一個(gè)類設(shè)置成不變類。
- 在對(duì)其他類的引用上,將引用其他對(duì)象的次數(shù)降到最低。
- 不暴露類的屬性成員,而應(yīng)該提供相應(yīng)的訪問器(set 和 get 方法)。
- 謹(jǐn)慎使用序列化(Serializable)功能。
合成復(fù)用原則
定義: 也叫組合/聚合復(fù)用原則。它要求在軟件復(fù)用時(shí),要盡量先使用組合或者聚合等關(guān)聯(lián)關(guān)系來(lái)實(shí)現(xiàn),其次才考慮使用繼承關(guān)系來(lái)實(shí)現(xiàn)。
如果要使用繼承關(guān)系,則必須嚴(yán)格遵循里氏替換原則。合成復(fù)用原則同里氏替換原則相輔相成的,兩者都是開閉原則的具體實(shí)現(xiàn)規(guī)范。
作用:
通常類的復(fù)用分為繼承復(fù)用和合成復(fù)用兩種,繼承復(fù)用雖然有簡(jiǎn)單和易實(shí)現(xiàn)的優(yōu)點(diǎn),但它也存在以下缺點(diǎn)。
- 繼承復(fù)用破壞了類的封裝性。因?yàn)槔^承會(huì)將父類的實(shí)現(xiàn)細(xì)節(jié)暴露給子類,父類對(duì)子類是透明的,所以這種復(fù)用又稱為“白箱”復(fù)用。
- 子類與父類的耦合度高。父類的實(shí)現(xiàn)的任何改變都會(huì)導(dǎo)致子類的實(shí)現(xiàn)發(fā)生變化,這不利于類的擴(kuò)展與維護(hù)。
- 它限制了復(fù)用的靈活性。從父類繼承而來(lái)的實(shí)現(xiàn)是靜態(tài)的,在編譯時(shí)已經(jīng)定義,所以在運(yùn)行時(shí)不可能發(fā)生變化。
采用組合或聚合復(fù)用時(shí),可以將已有對(duì)象納入新對(duì)象中,使之成為新對(duì)象的一部分,新對(duì)象可以調(diào)用已有對(duì)象的功能,它有以下優(yōu)點(diǎn)。
- 它維持了類的封裝性。因?yàn)槌煞謱?duì)象的內(nèi)部細(xì)節(jié)是新對(duì)象看不見的,所以這種復(fù)用又稱為“黑箱”復(fù)用。
- 新舊類之間的耦合度低。這種復(fù)用所需的依賴較少,新對(duì)象存取成分對(duì)象的唯一方法是通過成分對(duì)象的接口。
- 復(fù)用的靈活性高。這種復(fù)用可以在運(yùn)行時(shí)動(dòng)態(tài)進(jìn)行,新對(duì)象可以動(dòng)態(tài)地引用與成分對(duì)象類型相同的對(duì)象。
實(shí)現(xiàn):
合成復(fù)用原則是通過將已有的對(duì)象納入新對(duì)象中,作為新對(duì)象的成員對(duì)象來(lái)實(shí)現(xiàn)的,新對(duì)象可以調(diào)用已有對(duì)象的功能,從而達(dá)到復(fù)用。
總結(jié)
| 設(shè)計(jì)原則 | 一句話歸納 | 目的 |
|---|---|---|
| 開閉原則 | 對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉 | 降低維護(hù)帶來(lái)的新風(fēng)險(xiǎn) |
| 依賴倒置原則 | 高層不應(yīng)該依賴低層,要面向接口編程 | 更利于代碼結(jié)構(gòu)的升級(jí)擴(kuò)展 |
| 單一職責(zé)原則 | 一個(gè)類只干一件事,實(shí)現(xiàn)類要單一 | 便于理解,提高代碼的可讀性 |
| 接口隔離原則 | 一個(gè)接口只干一件事,接口要精簡(jiǎn)單一 | 功能解耦,高聚合、低耦合 |
| 迪米特法則 | 不該知道的不要知道,一個(gè)類應(yīng)該保持對(duì)其它對(duì)象最少的了解,降低耦合度 | 只和朋友交流,不和陌生人說(shuō)話,減少代碼臃腫 |
| 里氏替換原則 | 不要破壞繼承體系,子類重寫方法功能發(fā)生改變,不應(yīng)該影響父類方法的含義 | 防止繼承泛濫 |
| 合成復(fù)用原則 | 盡量使用組合或者聚合關(guān)系實(shí)現(xiàn)代碼復(fù)用,少使用繼承 | 降低代碼耦合 |
參考資料
- Java設(shè)計(jì)模式:23種設(shè)計(jì)模式全面解析(超級(jí)詳細(xì))
- 大話設(shè)計(jì)模式