最近看了一些的設(shè)計(jì)原則與設(shè)計(jì)模式相關(guān)的知識绿淋,基本每種設(shè)計(jì)模式都是基于六大設(shè)計(jì)原則去進(jìn)行設(shè)計(jì)的嫂拴,也了解了一些設(shè)計(jì)模式的優(yōu)缺點(diǎn)腰耙,而它們的很多優(yōu)點(diǎn)是由于符合設(shè)計(jì)原則帶來的便利氛堕,而缺點(diǎn)則是在一定程度上的破壞設(shè)計(jì)原則導(dǎo)致的結(jié)果立肘”呃ぃ基于上面各種現(xiàn)象,我想到一個(gè)問題谅年,是否能通過設(shè)計(jì)原則去建立一個(gè)滿足六大原則的模型茧痒,然后使用這個(gè)模型去分析這些設(shè)計(jì)模式在功能穩(wěn)定性和擴(kuò)展性上的能力。
為什么基于設(shè)計(jì)原則去設(shè)計(jì)
從OOD(面向?qū)ο笤O(shè)計(jì))的設(shè)計(jì)目標(biāo)說起融蹂,它的設(shè)計(jì)目標(biāo)希望軟件系統(tǒng)能做到以下幾點(diǎn):
- 可擴(kuò)展:新特性能夠很容易的添加到現(xiàn)有系統(tǒng)中旺订,不會(huì)影響原本的東西
- 可修改:當(dāng)修改某一部分的代碼時(shí)弄企,不會(huì)影響到其它不相關(guān)的部分
- 可替代:將系統(tǒng)中某部分的代碼用其它有相同接口的類替換時(shí),不會(huì)影響到現(xiàn)有系統(tǒng)
為了便于我們設(shè)計(jì)出易于維護(hù)和擴(kuò)展的軟件系統(tǒng)区拳,于是就出現(xiàn)了一些符合OOD要求的設(shè)計(jì)原則拘领,應(yīng)用這些原則會(huì)使得我們的程序具有良好的擴(kuò)展性和穩(wěn)定性,這也是這篇文章標(biāo)題的想說明的問題樱调。
使用六大設(shè)計(jì)原則推導(dǎo)分析模型
六大設(shè)計(jì)原則的介紹詳見:設(shè)計(jì)模式基本原則及其作用
單一職責(zé)原則要求我們對類和接口進(jìn)行職責(zé)上的明確劃分院究,而接口隔離原則要求我們在滿足單一職責(zé)原則的基礎(chǔ)上對接口進(jìn)行更加細(xì)致的劃分,只將別人需要的部分暴露出去本涕,這樣同時(shí)也滿足迪米特法則业汰,因此,我們可以模擬部分類圖如下
接下來看一下怎么樣才能滿足依賴倒置原則
根據(jù)定義菩颖,抽象之間可以互相依賴样漆,抽象不依賴細(xì)節(jié),細(xì)節(jié)依賴抽象晦闰,可以得到部分圖如下
如果我們要做到迪米特法則放祟,那么我們應(yīng)該
1.?只與朋友類(成員變量、輸入輸出參數(shù))交流
????????這就要求兩個(gè)類如果想產(chǎn)生關(guān)系呻右,那么應(yīng)該在成員變量或者接口的定義中體現(xiàn)出來跪妥,而盡量不要在接口方法的實(shí)現(xiàn)上引入其他未被全局聲明的依賴關(guān)系。
2.?讓別人知道的東西越少越好
????????在兩部分之間的依賴声滥,只暴露對方需要的部分眉撵,可以考慮在兩部分之間加一層協(xié)調(diào)來減少暴露的部分或進(jìn)行進(jìn)一步的封裝,以減少使用者真正需要了解的部分落塑。
在兩部分之間的關(guān)系上可以得到如下表示
里氏替換原則要求父類出現(xiàn)的地方纽疟,子類都可以出現(xiàn),并且能夠得到正確的執(zhí)行結(jié)果憾赁。
????????我們直觀的感受就是子類繼承了父類所有的方法污朽,使用子類去替換父類并不會(huì)導(dǎo)致程序編譯出錯(cuò),那么如果違反里氏替換原則只有一種可能龙考,就是子類替換成父類了之后會(huì)使得程序運(yùn)行結(jié)果與預(yù)期不符蟆肆。
? ? ? ? 為什么子類替換成父類之后可能導(dǎo)致運(yùn)行結(jié)果與預(yù)期不符?因?yàn)樵镜某绦蚴腔诟割惾ピO(shè)計(jì)的晦款,那么如果替換成子類的話炎功,如果是同名方法(且父類和子類方法參數(shù)類型也有繼承關(guān)系),就可能導(dǎo)致程序原意是調(diào)用父類定義的A(a)方法而在運(yùn)替換成子類之后調(diào)用了子類定義的A(b)方法柬赐,那么如何避免這種情況亡问?重載的時(shí)候子類方法參數(shù)范圍應(yīng)該大于父類方法參數(shù)范圍,原來的程序是基于父類設(shè)計(jì)的肛宋,就不會(huì)導(dǎo)致應(yīng)該調(diào)用父類定義的方法而調(diào)用了子類方法的情況州藕。
開閉原則很重要,但是并沒有在類之間的關(guān)系上給出明確的指示酝陈,因?yàn)槠渌麕讉€(gè)原則是對開閉原則的一些實(shí)現(xiàn)床玻,我們對其他幾個(gè)原則的遵守實(shí)際上也是對開閉原則的一種遵守。但是我們在設(shè)計(jì)完成之后還是要對是否滿足開閉原則多加思考沉帮,比如為了體現(xiàn)迪米特原則锈死,我們就有可能在依賴之間添加一層封裝,這時(shí)候就很有可能會(huì)導(dǎo)致以后在擴(kuò)展的時(shí)候穆壕,會(huì)侵害到這層封裝地代碼待牵,從這個(gè)角度看就影響了開閉原則的實(shí)現(xiàn)。
綜上喇勋,我們整合好所有的部分缨该,可以下面的結(jié)果
這個(gè)模型并不是一個(gè)具體的模,但是如果一個(gè)設(shè)計(jì)能滿足這樣的結(jié)構(gòu)川背,從理論上來分析贰拿,至少具有以下優(yōu)點(diǎn)
1.?職責(zé)清晰:上面紫色部分嚴(yán)格按照單一職責(zé)以及接口隔離原則劃分,每個(gè)接口和類具有的功能清晰
2.?解耦程度高:類之間只使用抽象作為互相溝通熄云,不涉及對細(xì)節(jié)的處理膨更,各個(gè)模塊可以脫離其他模塊的細(xì)節(jié)并行開發(fā),同時(shí)對細(xì)節(jié)進(jìn)行修改的時(shí)候不會(huì)影響到其他模塊
3.?可擴(kuò)展性強(qiáng):這里說的擴(kuò)展性缴允,指的是葉子節(jié)點(diǎn)的擴(kuò)展性荚守,如果我要進(jìn)行擴(kuò)展的時(shí)候,只需要在繼承樹的最下層添加一個(gè)葉子练般,而其他代碼都不需要修改健蕊,這樣的擴(kuò)展能力是非常高的,當(dāng)然踢俄,這是基于模型分析的理想狀況
4.?穩(wěn)定性:生產(chǎn)環(huán)境的代碼一般都是穩(wěn)定的缩功,我們在做擴(kuò)展的時(shí)候應(yīng)該盡量保證這部分代碼原有的穩(wěn)定性——即盡量做到不修改已存在的代碼,基于這個(gè)模型具有的耦合度低都办、擴(kuò)展性強(qiáng)且不對原有代碼存在侵害的特點(diǎn)嫡锌,理想情況下是可以保證其穩(wěn)定性的。
????????雖然嚴(yán)格按照這樣的模型去設(shè)計(jì)會(huì)帶來一些好處琳钉,但是在很多場景下會(huì)導(dǎo)致程序結(jié)構(gòu)變得非常復(fù)雜势木,以及不斷擴(kuò)展帶來的葉子結(jié)點(diǎn)過多,程序復(fù)雜度提高歌懒,降低維護(hù)性的問題啦桌。
????????但是從穩(wěn)定性和擴(kuò)展性的角度看,這樣的設(shè)計(jì)基于設(shè)計(jì)原則,是比較合理的結(jié)構(gòu)甫男,很多設(shè)計(jì)模式在這中結(jié)構(gòu)的基礎(chǔ)上進(jìn)行了取舍且改,甚至對違反了一些設(shè)計(jì)原則,但是這并不代表那種設(shè)計(jì)模式是不合理的板驳,在特定的場景下使用是非常合適的又跛。因此我們不能使用這樣的模型去構(gòu)建,或者說去推導(dǎo)一些設(shè)計(jì)模式出來若治,但是可以通過它對已存在的設(shè)計(jì)模式進(jìn)行直觀的分析慨蓝,通過比較特定設(shè)計(jì)模式類間關(guān)系與這個(gè)模型的異同,分析出其所滿足的設(shè)計(jì)原則端幼,這樣帶來的好處礼烈,以及其違背的設(shè)計(jì)原則,這樣做帶來的缺點(diǎn)與限制婆跑。
上面的圖有些復(fù)雜此熬,大多數(shù)情況下可以使用如下簡化圖進(jìn)行分析
接下來會(huì)根據(jù)這套模型,對我們常見的設(shè)計(jì)模式在穩(wěn)定性和擴(kuò)展性的能力上進(jìn)行分析洽蛀。
參考文獻(xiàn)《設(shè)計(jì)模式之禪》摹迷,這本書的作者非常用心~