设计模式(四)结构型模式
前言
結(jié)構(gòu)型設計模式,主要研究:
- 主要有哪些場景使用結(jié)構(gòu)型設計模式;
- 每種場景應該使用何種設計模式;
- 以程序中的功能為核心,研究程序功能的組織結(jié)構(gòu)。所以這一章,我們要把“功能結(jié)構(gòu)”作為研究的核心。
下面分別對幾種結(jié)構(gòu)型模式加以說明。
1. 適配器模式
示例:適配器模式
使用場景
想要在系統(tǒng)中添加某個功能,類似的功能在其他項目中已經(jīng)實現(xiàn),而且經(jīng)過分析,舊的接口可以經(jīng)過適當?shù)姆庋b,轉(zhuǎn)換成新的適用于當前系統(tǒng)的接口。這樣可以最大程度地復用已有的模塊。
原理
通過適配器將已有功能的舊的接口,轉(zhuǎn)換為新的接口,從而實現(xiàn)使已有的功能為新的系統(tǒng)服務的目的。
不適用的情況
以下情況下,不要使用適配器模式:
- 舊的接口無法轉(zhuǎn)換成新的接口;
- 寫適配器的工作量幾乎可以重寫所需的功能時。
使用須知
適配器模式其實是一種取巧的做法,在使用時需要慎重考慮。已有功能通過適配器集成到新的系統(tǒng)后,如果出現(xiàn)問題或者需要進行功能擴展,其維護成本是一個需要考慮的問題。例如,已有功能是否使用了過時的技術(shù),或者資料不全,都可能成為項目的風險所在。
本質(zhì)
適配器模式本質(zhì)上是通過將一接口封裝成另一種接口,實現(xiàn)了模塊功能復用。
2. 橋接模式
示例:橋接模式
使用場景
橋接模式是少用繼承,多用組合的第一例。
拿菜鳥教程中的例子來說,假如我們現(xiàn)在要實現(xiàn)圓類,包括紅色圓和綠色圓兩種圓。
首先容易想到的方法是,先寫一個圓基類,并添加一個虛(virtual)的繪制函數(shù)。然后分別派生出紅色圓類和綠色圓類,在子類中分別重新實現(xiàn)繪制函數(shù),將圓繪制成指定的顏色。
在這種簡單的例子中,使用繼承是沒什么問題的。但是假如圓基類還有一個虛函數(shù),此虛函數(shù)用于對圓進行旋轉(zhuǎn)。旋轉(zhuǎn)分為兩種,順時針和逆時針旋轉(zhuǎn)。我們想要四種類型的圓:
- 順時針旋轉(zhuǎn)的紅色圓
- 順時針旋轉(zhuǎn)的綠色圓
- 逆時針旋轉(zhuǎn)的紅色圓
- 逆時針旋轉(zhuǎn)的綠色圓
如何使用繼承來實現(xiàn)呢?難道要派生出四個子類嗎?如果還有其他功能組合呢?要多少個類呢?這樣下去無疑會導致“類的數(shù)量爆炸”問題。
原理
結(jié)構(gòu)型模式是研究程序功能組織方法的設計模式。當程序中需要對幾種功能相互組合時,應該用組合,不要用繼承。
橋接模式下,對于每個功能,應該提取出一個接口類,這個接口類可以有不同的實現(xiàn)。而代表不同的功能接口,可以作為主體類(此例中為圓類)的成員變量,放在一起。需要什么功能,就new哪種接口子類,保存在接口變量中,這樣就可以把不同的功能組合起來。
這樣一來,類的數(shù)量會保持在最低水平。
相對于繼承,橋接模式相當于把主體類中的每個虛函數(shù)都單獨提取出來,構(gòu)成 一個接口類。這個接口類連接了具體實現(xiàn)和主體類,所以這個模式叫橋接模式。這個名字其實不是很能反映此模式的內(nèi)涵,其實叫“功能組合模式”更為貼切。
可能有的小伙伴會說,上面的功能其實用C語言實現(xiàn)不是更簡單嗎?
- 用一個結(jié)構(gòu)體代表圓,有半徑、邊框?qū)挾鹊葘傩?#xff1b;
- 每種功能就是一個函數(shù),參數(shù)為圓的結(jié)構(gòu)體。
這不就完成了嗎?是的!
這個場景下,確實使用C語言實現(xiàn)更簡單,不需要使用C++面向?qū)ο蟮娜魏翁匦约纯蓪崿F(xiàn)。可以看出,C++的面向?qū)ο蟮奶匦?#xff0c;并不是萬能的,并不是在所有情況下都是最優(yōu)的,甚至有時候不如C語言簡單直接。從另一個角度說明,大家在面向?qū)ο缶幊痰臅r候,不要把自己的思維局限于面向?qū)ο?#xff0c;面向?qū)ο笏枷朐谝恍r候,是不如面向過程的,甚至會把功能結(jié)構(gòu)復雜化,設計到最后導致代碼難以維護都是有可能的。
使用須知
橋接模式會導致代碼中存在設計模式的代碼,會增加代碼的理解難度。相對來說,積極作用還是遠大于副作用的。
本質(zhì)
橋接模式的本質(zhì)是:
如果項目中出現(xiàn)了功能組合的場景,使用繼承封裝功能是錯誤做法,要把功能單獨提取出來分別封裝好以后,再進行組合。
3. 過濾器模式
示例:過濾器模式
使用場景
現(xiàn)有一組對象,我們想要根據(jù)不同的過濾條件,篩選出符合條件的一部分對象。
一般寫法
最簡單粗暴的方法是,在需要進行篩選過濾的地方,直接遍歷對象數(shù)組,在循環(huán)體內(nèi)進行條件判斷。這種寫法的優(yōu)點是簡單直接,缺點是如果有多個地方需要使用篩選過濾功能,則需要在多個地方編寫重復的代碼,這會降低代碼的復用性和可維護性。
推薦寫法
使用過濾器模式,把篩選功能封裝起來使用即可。接口也很好定義,輸入對象數(shù)組,輸出符號條件的對象數(shù)組。
本質(zhì)
過濾器模式的本質(zhì)是:
當需要從一組對象中過濾出一部分符合條件的對象時,可以考慮將每種過濾功能都封裝為一個類,提高代碼復用性和可維護性。
4. 組合模式
示例:組合模式
組合模式是一種樹形的對象組織結(jié)構(gòu),在建造者模式已有相關(guān)說明,這里不再贅述。
5. 裝飾器模式
示例:裝飾器模式
使用場景
裝飾器模式的研究對象有兩個:
- 已有功能
- 擴展功能
當我們需要擴展一個類的功能,但是又不想直接在此類上進行改動時,一般的做法是使用繼承來實現(xiàn)。繼承出來的子類具有父類的屬性和方法,在父類基礎(chǔ)上可以添加新的功能。
除了繼承,還可以使用裝飾器模式。裝飾器模式是指,新建一個擴展類,將被擴展類的對象作為擴展類的成員變量保存,在擴展類中,操作被擴展類,實現(xiàn)新的方法和功能。
簡單來說,裝飾器模式就是新建一個類把已有類的功能包裝起來,實現(xiàn)新的功能。
使用須知
裝飾器模式和繼承各有優(yōu)缺點,使用時要加以權(quán)衡,選擇最優(yōu)的方案。
本質(zhì)
從本質(zhì)上說:
裝飾器模式通過將已有功能作為成員變量整個封裝(包裝)起來,擴展的新功能,和已有功能耦合最小,互不影響。
6. 外觀模式
示例:裝飾器模式
本質(zhì)
這個模式比較簡單不再贅述。其本質(zhì)是:
將已有功能封裝起來,提供更易于使用的接口,屏蔽更多實現(xiàn)細節(jié),等于是加了一個中間層。
7. 享元模式
示例:享元模式
按照我們的分類,此模式應該屬于創(chuàng)建型模式。它是借助工廠模式來實現(xiàn)一個對象緩沖池,減少對象數(shù)量 ,加速創(chuàng)建速度。這里不再贅述。
8. 代理模式
示例:代理模式
應用場景
代理模式就是中介模式。例如我們想要租房,原本租房是發(fā)生在租客和房東之間的事務,但中介的出現(xiàn),雖然會有一定的費用(損耗),但是整個過程的推進會更加順利。代理模式,用來將兩個比較難以直接溝通的功能主體關(guān)聯(lián)起來,實現(xiàn)二者交互。
使用須知
和租房找中介一樣,只有在必要的時候才找,否則就是浪費資源,只有在非用不可的時候才建議使用代理模式。
本質(zhì)
代理模式的本質(zhì)是:
代理模式封裝了溝通所需的所有功能,將兩個難以直接溝通的功能主體連接起來,起到了橋梁作用。
結(jié)語
結(jié)構(gòu)型模式,就是以功能為核心,研究功能轉(zhuǎn)換、功能調(diào)用、功能組合、功能封裝等各種情形下,將哪些功能封裝到哪些類中,更加高效地實現(xiàn)需求,提升代碼的可維護性。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的设计模式(四)结构型模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 年轻人为什么换不动手机了引热议:更注重实
- 下一篇: python解析html的库_用pyth