設(shè)計(jì)模式基礎(chǔ)
軟件設(shè)計(jì)模式的概念
軟件設(shè)計(jì)模式( Software Design Pattern )蹬叭,又稱設(shè)計(jì)模式乡摹, 是一套被反復(fù)使用、多數(shù)人知曉的缩赛、經(jīng)過分類編目的耙箍、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。它描述了在軟件設(shè)計(jì)過程中的一些不斷重復(fù)發(fā)生的問題酥馍,以及該問題的解決方案辩昆。也就是說,它是解決特定問題的一系列套路旨袒,是前輩們的代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)汁针,具有一定的普遍性,可以反復(fù)使用砚尽。其目的是為了提高代碼的可重用性施无、代碼的可讀性和代碼的可靠性。
軟件設(shè)計(jì)模式的基本要素
軟件設(shè)計(jì)模式使人們可以更加簡單方便地復(fù)用成功的設(shè)計(jì)和體系結(jié)構(gòu)必孤,它通常包含以下幾個(gè)基 本要素:模式名稱猾骡、別名、動(dòng)機(jī)敷搪、問題兴想、解決方案、效果赡勘、結(jié)構(gòu)嫂便、模式角色、合作關(guān)系闸与、實(shí)現(xiàn)方法毙替、適用性、已知應(yīng)用践樱、例程蔚龙、模式擴(kuò)展和相關(guān)模式等,其中最關(guān)鍵的元素包括以下4個(gè)主要部分映胁。
1. 模式名稱
每一個(gè)模式都有自己的名字京痢,通常用一兩個(gè)詞來描述飞崖,可以根據(jù)模式的問題、特點(diǎn)、解決方案砸捏、功能和效果來命名假栓。模式名稱( Pattern Name )有助于我們理解和記憶該模式柠硕,也方便我們來討論自己的設(shè)計(jì)飒货。
2. 問題
問題( Problem )描述了該模式的應(yīng)用環(huán)境,即何時(shí)使用該模式廷臼。它解釋了設(shè)計(jì)問題和問題存在的前因后果苍在,以及必須滿足的一系列先決條件绝页。
3. 解決方案
模式問題的解決方案( Solution )包括設(shè)計(jì)的組成成分、它們之間的相互關(guān)系及各自的職責(zé)和協(xié)作方式寂恬。因?yàn)槟J骄拖褚粋€(gè)模板续誉,可應(yīng)用于多種不同場(chǎng)合,所以解決方案并不描述一個(gè)特定而具體的設(shè)計(jì)或?qū)崿F(xiàn) 初肉,而是提供設(shè)計(jì)問題的抽象描述和怎樣用一個(gè)具有一般意義的元素組合(類或?qū)ο蟮慕M合)來解決這個(gè)問題酷鸦。
4. 效果
描述了模式的應(yīng)用效果以及使用該模式應(yīng)該權(quán)衡的問題,即模式的優(yōu)缺點(diǎn)牙咏。主要是對(duì)時(shí)間和空 間的衡量臼隔,以及該模式對(duì)系統(tǒng)的靈活性、擴(kuò)充性妄壶、可移植性的影響摔握,也考慮其實(shí)現(xiàn)問題。顯式地列出這些效果( Consequence )對(duì)理解和評(píng)價(jià)這些模式有很大的幫助丁寄。
GoF 的 23 種設(shè)計(jì)模式簡介
設(shè)計(jì)模式有兩種分類方法氨淌,即根據(jù)模式的目的來分和根據(jù)模式的作用的范圍來分。
根據(jù)目的來分
根據(jù)模式是用來完成什么工作來劃分狡逢, 這種方式可分為創(chuàng)建型模式、結(jié)構(gòu)型模式和行為型模 式 3 種拼卵。
1.創(chuàng)建型模式
用于描述“怎樣創(chuàng)建對(duì)象”奢浑,它的主要特點(diǎn)是“將對(duì)象的創(chuàng)建與使用分離“。GoF 中提供了單例腋腮、原型雀彼、工廠方法、抽象工廠即寡、建造者等 5 種創(chuàng)建型模式徊哑。
2.結(jié)構(gòu)型模式
用于描述如何將類或?qū)ο蟀茨撤N布局組成更大的結(jié)構(gòu),GoF 中提供了代理聪富、適配器莺丑、橋接、裝飾墩蔓、外觀梢莽、享元、組合等 7 種結(jié)構(gòu)型模式奸披。
3.行為型模式
用于描述類或?qū)ο笾g怎樣相互協(xié)作共同完成單個(gè)對(duì)象都無法單獨(dú)完成的任務(wù)昏名,以及怎樣分配職責(zé)。 GoF 中提供了模板方法阵面、策略轻局、命令洪鸭、職責(zé)鏈、狀態(tài)仑扑、觀察者览爵、中介者、迭代器夫壁、訪問者拾枣、備忘錄、解釋器等 11 種行為型模式盒让。
根據(jù)作用范圍來分
根據(jù)模式是主要用于類上還是主要用于對(duì)象上來分 梅肤, 這種方式可分為類模式和對(duì)象模式兩種。
1. 類模式
用于處理類與子類之間的關(guān)系邑茄,這些關(guān)系通過繼承來建立姨蝴,是靜態(tài)的,在編譯時(shí)刻便確定下來了肺缕。GoF 中的工廠方法左医、(類)適配器、模板方法同木、解釋器屬于該模式浮梢。
2. 對(duì)象模式
用于處理對(duì)象之間的關(guān)系,這些關(guān)系可以通過組合或聚合來實(shí)現(xiàn)彤路,在運(yùn)行時(shí)刻是可以變化的秕硝,更具動(dòng)態(tài)性。 GoF 中除了以上 4 種洲尊,其他的都是對(duì)象模式远豺。
范圍\目的 | 創(chuàng)建型模式 | 結(jié)構(gòu)型模式 | 行為型模式 |
---|---|---|---|
類模式 | 工廠方法 | (類)適配器 | 模板方法、解釋器 |
對(duì)象模式 | 單例 原型 抽象工廠 建造者 | 代理 (對(duì)象)適配器 橋接 裝飾 外觀 享元 組合 | 策略 命令 職責(zé)鏈 狀態(tài) 觀察者 中介者 迭代器 訪問者 備忘錄 |
GoF 的 23 種設(shè)計(jì)模式的功能
前面說明了 GoF 的 23 種設(shè)計(jì)模式的分類坞嘀,現(xiàn)在對(duì)各個(gè)模式的功能進(jìn)行介紹躯护。
單例( Singleton )模式:某個(gè)類只能生成一個(gè)實(shí)例,該類提供了一個(gè)全局訪問點(diǎn)供外部獲取該實(shí)例丽涩,其拓展是有限多例模式棺滞。
原型( Prototype )模式:將一個(gè)對(duì)象作為原型,通過對(duì)其進(jìn)行復(fù)制而克隆出多個(gè)和原型類似的新實(shí)例矢渊。
工廠方法( Facto可 Method )模式:定義一個(gè)用于創(chuàng)建產(chǎn)品的接口检眯,由子類決定生產(chǎn)什么產(chǎn)品。
抽象工廠( Abstract Factory )模式:提供一個(gè)創(chuàng)建產(chǎn)品族的接口昆淡,其每個(gè)子類可以生產(chǎn)一系列相關(guān)的產(chǎn)品锰瘸。
建造者( Builder )模式:將一個(gè)復(fù)雜對(duì)象分解成多個(gè)相對(duì)簡單的部分,然后根據(jù)不同需要分別創(chuàng)建它們昂灵,最后構(gòu)建成該復(fù)雜對(duì)象避凝。
代理( Proxy )模式:為某對(duì)象提供一種代理以控制對(duì)該對(duì)象的訪問舞萄。 即客戶端通過代理間 接地訪問該對(duì)象 , 從而限制管削、增強(qiáng)或修改該對(duì)象的一些特性倒脓。
適配器( Adapter )模式: 將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口,使得原本由于接口不兼容而不能一起工作的那些類能一起工作含思。
橋接( Bridge )模式:將抽象與實(shí)現(xiàn)分離崎弃,使它們可以獨(dú)立變化。它是用組合關(guān)系代替繼承關(guān)系來實(shí)現(xiàn)含潘,從而降低了抽象和實(shí)現(xiàn)這兩個(gè)可變維度的相合度饲做。
裝飾( Decorator )模式:動(dòng)態(tài)的給對(duì)象增加一些職責(zé),即增加其額外的功能遏弱。
外觀( Facade )模式:為多個(gè)復(fù)雜的子系統(tǒng)提供一個(gè)一致的接口盆均,使這些子系統(tǒng)更加容易被訪問。
享元( Flyweight )模式:運(yùn)用共享技術(shù)來有效地支持大量細(xì)粒度對(duì)象的復(fù)用漱逸。
組合( Composite )模式:將對(duì)象組合成樹狀層次結(jié)構(gòu)泪姨,使用戶對(duì)單個(gè)對(duì)象和組合對(duì)象具有一致的訪問性。
模板方法( Template Method )模式:定義一個(gè)操作中的算法骨架饰抒,而將算法的一些步驟延遲到子類中肮砾,使得子類可以不改變?cè)撍惴ńY(jié)構(gòu)的情況下重定義該算法的某些特定步驟。
策略( Strategy )模式:定義了一系列算法袋坑,并將每個(gè)算法封裝起來仗处,使它們可以相互替換,且算法的改變不會(huì)影響使用算法的客戶 咒彤。
命令( Command )模式:將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象疆柔,使發(fā)出請(qǐng)求的責(zé)任和執(zhí)行請(qǐng)求的責(zé)任分割開咒精。
職責(zé)鏈( Chain of Responsibility )模式:把請(qǐng)求從鏈中的一個(gè)對(duì)象傳到下一個(gè)對(duì)象镶柱,直到請(qǐng)求被響應(yīng)為止。通過這種方式去除對(duì)象之間的耦合模叙。
狀態(tài)( State )模式:允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)發(fā)生改變時(shí)改變其行為能力 歇拆。
觀察者( Observer )模式:多個(gè)對(duì)象間存在一對(duì)多關(guān)系,當(dāng)一個(gè)對(duì)象發(fā)生改變時(shí)范咨,把這種改變通知給其他多個(gè)對(duì)象故觅,從而影響其他對(duì)象的行為 。
中介者( Mediator )模式:定義一個(gè)中介對(duì)象來簡化原有對(duì)象之間的交互關(guān)系渠啊,降低系統(tǒng)中對(duì)象間的相合度输吏,使原有對(duì)象之間不必相互了解。
迭代器( Iterator )模式:提供一種方法來順序訪問聚合對(duì)象中的一系列數(shù)據(jù) 替蛉,而不暴露聚合對(duì)象的內(nèi)部表示贯溅。
訪問者( Visitor )模式:在不改變集合元素的前提下拄氯,為一個(gè)集合中的每個(gè)元素提供多種訪問方式,即每個(gè)元素有多個(gè)訪問者對(duì)象訪問它浅。
備忘錄( Memento )模式:在不破壞封裝性的前提下译柏,獲取并保存一個(gè)對(duì)象的內(nèi)部狀態(tài),以便以后恢復(fù)它姐霍。
解釋器( Interpreter )模式:提供如何定義語言的文法鄙麦,以及對(duì)語言句子的解釋方法,即解釋器镊折。
這里必須強(qiáng)調(diào)一點(diǎn)胯府,這 23 種設(shè)計(jì)模式不是孤立存在的,很多模式之間存在一定的關(guān)聯(lián)關(guān)系腌乡,在大的系統(tǒng)開發(fā)中常常同時(shí)使用多種設(shè)計(jì)模式
面向?qū)ο蟮脑O(shè)計(jì)原則
在軟件開發(fā)中盟劫,為了提高軟件系統(tǒng)的可維護(hù)性和可復(fù)用性,增加軟件的可擴(kuò)展性和靈活性与纽,程序員要盡量根據(jù)以下 7 條原則來開發(fā)程序侣签,從而提高軟件開發(fā)效率、節(jié)約軟件開發(fā)成本和維護(hù)成本急迂。
開閉原則
開閉原則的定義
開閉原則( Open Closed Principle影所,OCP )是由勃蘭特·梅耶( Bertrand Meyer )提出,他在 1988 年的著作《面向?qū)ο筌浖?gòu)造》中提出:軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放僚碎,對(duì)修改關(guān)閉猴娩,這就是開閉原則的經(jīng)典定義
這里的軟件實(shí)體包括以下幾個(gè)部分:
- 項(xiàng)目中劃分出的模塊
- 類與接口
- 方法
開閉原則的含義是:當(dāng)應(yīng)用的需求改變時(shí),在不修改軟件實(shí)體的源代碼或者二進(jìn)制代碼的前提下勺阐,可以擴(kuò)展模塊的功能卷中,使其滿足新的需求。
開閉原則的作用
開閉原則是面向?qū)ο蟪绦蛟O(shè)計(jì)的終極目標(biāo)渊抽,它使軟件實(shí)體擁有一定的適應(yīng)性和靈活性的同時(shí)具 備穩(wěn)定性和延續(xù)性蟆豫。具體來說,其作用如下懒闷。
對(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)方法
可以通過“抽象約束闹炉、封裝變化”來實(shí)現(xiàn)開閉原則,即通過接口或者抽象類為軟件實(shí)體定義一 個(gè)相對(duì)穩(wěn)定的抽象層润樱,而將相同的可變因素封裝在相同的具體實(shí)現(xiàn)類中渣触。因?yàn)槌橄箪`活性好, 適應(yīng)性廣壹若,只要抽象的合理嗅钻,可以基本保持軟件架構(gòu)的穩(wěn)定。而軟件中易變的細(xì)節(jié)可以從抽象派生來的實(shí)現(xiàn)類來進(jìn)行擴(kuò)展店展,當(dāng)軟件需要發(fā)生變化時(shí)养篓,只需要根據(jù)需求重新派生一個(gè)實(shí)現(xiàn)類來擴(kuò)展就可以了。
里式替換原則
里氏替換原則的定義
里氏替換原則( Liskov Substitution Principle, LSP )由麻省理工學(xué)院計(jì)算機(jī)科學(xué)實(shí)驗(yàn)室的里斯科夫( Liskov )女士在 1987 年的“面向?qū)ο蠹夹g(shù)的高峰會(huì)議”( OOPSLA )上發(fā)表的一篇文章《數(shù)據(jù)抽象和層次》( Data Abstraction and Hierarchy )里提出來的赂蕴,她提出:繼承必須確保超類所擁有的性質(zhì)在子類中仍然成立柳弄。
里氏替換原則主要闡述了有關(guān)繼承的一些原則,也就是什么時(shí)候應(yīng)該使用繼承概说,什么時(shí)候不應(yīng) 該使用繼承碧注,以及其中蘊(yùn)含的原理。里氏替換原是繼承復(fù)用的基礎(chǔ)糖赔,它反映了基類與子類之間的關(guān)系萍丐,是對(duì)開閉原則的補(bǔ)充,是對(duì)實(shí)現(xiàn)抽象化的具體步驟的規(guī)范放典。
里式替換原則的作用
里氏替換原則的主要作用有以下幾點(diǎn):
- 里氏替換原則是實(shí)現(xiàn)開閉原則的重要方式之一逝变。
- 它克服了繼承中重寫父類造成的可復(fù)用性變差的缺點(diǎn)。
- 它是動(dòng)作正確性的保證奋构。即類的擴(kuò)展不會(huì)給已有的系統(tǒng)引入新的錯(cuò)誤壳影,降低了代碼出錯(cuò)的可能性。
里式替換原則的實(shí)現(xiàn)方法
里氏替換原則通俗來講就是:子類可以擴(kuò)展父類的功能弥臼,但不能改變父類原有的功能宴咧。也就是說:子類繼承父類時(shí),除添加新的方法完成新增功能外醋火,盡量不要重寫父類的方法悠汽。如果通過重寫父類的方法來完成新的功能箱吕,這樣寫起來雖然簡單芥驳,但是整個(gè)繼承體系的可復(fù)用性會(huì)比較差,特別是運(yùn)用多態(tài)比較頻繁時(shí)茬高,程序運(yùn)行出錯(cuò)的概率會(huì)非常大兆旬。
如果程序違背了里氏替換原則,則繼承類的對(duì)象在基類出現(xiàn)的地方會(huì)出現(xiàn)運(yùn)行錯(cuò)誤怎栽。這時(shí)其修正方法是:取消原來的繼承關(guān)系丽猬,重新設(shè)計(jì)它們之間的關(guān)系宿饱。
依賴倒置原則
依賴倒置原則的定義
依賴倒置原則( Dependence Inversion Principle , DIP )是 Object Mentor 公司總裁羅伯特·馬丁 ( Robert C. Martin )于 1996 年在 C++ Report 上發(fā)表的文章。其原始定義是:高層模塊不應(yīng)該依賴低層模塊脚祟,兩者都應(yīng)該依賴其抽象谬以;抽象不應(yīng)該依賴細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴抽象由桌。其核心思想是:要面向接口編程为黎,不要面向?qū)崿F(xiàn)編程。
依賴倒置原則是實(shí)現(xiàn)開閉原則的重要途徑之一行您,它降低了客戶與實(shí)現(xiàn)模塊之間的耦合铭乾。由于在 軟件設(shè)計(jì)中,細(xì)節(jié)具有多變性娃循,而抽象層則相對(duì)穩(wěn)定炕檩,因此以抽象為基礎(chǔ)搭建起來的架構(gòu)要比以細(xì)節(jié)為基礎(chǔ)搭建起來的架構(gòu)要穩(wěn)定得多。這里的抽象指的是接口或者抽象類捌斧,而細(xì)節(jié)是指具體的實(shí)現(xiàn)類笛质。使用接口或者抽象類的目的是制定好規(guī)范和契約,而不去涉及任何具體的操作捞蚂,把展現(xiàn)細(xì)節(jié)的任務(wù)交給它們的實(shí)現(xiàn)類去完成经瓷。
依賴倒置原則的作用
依賴倒置原則的主要作用有以下幾點(diǎn):
- 依賴倒置原則可以降低類間的耦合性。
- 依賴倒置原則可以提高系統(tǒng)的穩(wěn)定性洞难。
- 依賴倒置原則可以減少并行開發(fā)引起的風(fēng)險(xiǎn)舆吮。
- 依賴倒置原則可以提高代碼的可讀性和可維護(hù)性。
依賴倒置原則的實(shí)現(xiàn)方法
依賴倒置原則的目的是通過要面向接口的編程來降低類間的耦合性队贱,所以我們?cè)趯?shí)際編程中只 要遵循以下 4 點(diǎn)色冀,就能在項(xiàng)目中滿足這個(gè)規(guī)則 。
- 每個(gè)類盡量提供接口或抽象類柱嫌,或者兩者都具備锋恬。
- 變量的聲明類型盡量是接口或者是抽象類。
- 任何類都不應(yīng)該從具體類派生编丘。
- 使用繼承時(shí)盡量遵循里氏替換原則 与学。
單一職責(zé)原則
單一職責(zé)原則的定義
單一職責(zé)原則( Single Responsibility Principle, SRP )又稱單一功能原則,由羅伯特·C.馬都巫ァ( Robert C. Martin )于《敏捷軟件開發(fā):原則索守、模式和實(shí)踐》一書中提出的。這里的職責(zé)是指類變化的原因抑片,單一職責(zé)原則規(guī)定一個(gè)類應(yīng)該有且僅有一個(gè)引起它變化的原因卵佛,否則類應(yīng)該被拆分。
該原則提出對(duì)象不應(yīng)該承擔(dān)太多職責(zé),如果一個(gè)對(duì)象承擔(dān)了太多的職責(zé)截汪,至少存在以下兩個(gè)缺點(diǎn):
- 一個(gè)職責(zé)的變化可能會(huì)削弱或者抑制這個(gè)類實(shí)現(xiàn)其他職責(zé)的能力疾牲;
- 當(dāng)客戶端需要該對(duì)象的某一個(gè)職責(zé)時(shí),不得不將其他不需要的職責(zé)全都包含進(jìn)來衙解,從而造成冗余代碼或代碼的浪費(fèi)阳柔。
單一職責(zé)原則的優(yōu)點(diǎn)
單一職責(zé)原則的核心就是控制類的粒度大小、將對(duì)象解耦蚓峦、提高其內(nèi)聚性盔沫。如果遵循單一職責(zé) 原則將有以下優(yōu)點(diǎn)。
- 降低類的復(fù)雜度枫匾。一個(gè)類只負(fù)責(zé)一項(xiàng)職責(zé)架诞,其邏輯肯定要比負(fù)責(zé)多項(xiàng)職責(zé)簡單得多。
- 提高類的可讀性干茉。復(fù)雜性降低谴忧,自然其可讀性會(huì)提高。
- 提高系統(tǒng)的可維護(hù)性角虫≌次剑可讀性提高,那自然更容易維護(hù)了 戳鹅。
- 變更引起的風(fēng)險(xiǎn)降低均驶。變更是必然的,如果單一職責(zé)原則遵守得好枫虏,當(dāng)修改一個(gè)功能時(shí)妇穴, 可以顯著降低對(duì)其他功能的影響。
單一職責(zé)原則的實(shí)現(xiàn)方法
單一職責(zé)原則是最簡單但又最難運(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)死讹。
接口隔離原則
接口隔離原則的定義
接口隔離原則( Interface Segregation Principle , ISP )要求程序員盡量將臃腫龐大的接口拆分成更小的和更具體的接口瞒滴,讓接口中只包含客戶感興趣的方法。2002 年羅伯特·c.馬丁給“接口隔離原則”的定義是:客戶端不應(yīng)該被迫依賴于它不使用的方法赞警。該原則還有另外一個(gè)定義:一個(gè)類對(duì)另一個(gè)類的依賴應(yīng)該建立在最小的接口上妓忍。兩個(gè)定義的含義是:要為各個(gè)類建立它們需要的專用接口,而不要試圖去建立一個(gè)很龐大的接口供所有依賴它的類去調(diào)用愧旦。
接口隔離原則和單一職責(zé)都是為了提高類的內(nèi)聚性世剖、降低它們之間的耦合性,體現(xiàn)了封裝的思想忘瓦,但兩者是不同的:
- 單一職責(zé)原則注重的是職責(zé)搁廓,而接口隔離原則注重的是對(duì)接口依賴的隔離;
- 單一職責(zé)原則主要是約束類耕皮,它針對(duì)的是程序中的實(shí)現(xiàn)和細(xì)節(jié)境蜕;接口隔離原則主要約束接口,主要針對(duì)抽象和程序整體框架的構(gòu)建凌停。
接口隔離原則的優(yōu)點(diǎn)
接口隔離原則是為了約束接口粱年、降低類對(duì)接口的依賴性,遵循接口隔離原則有以下 5 個(gè)優(yōu)點(diǎn):
- 將臃腫龐大的接口分解為多個(gè)粒度小的接口罚拟,可以預(yù)防外來變更的擴(kuò)散台诗,提高系統(tǒng)的靈活 性和可維護(hù)性。
- 接口隔離提高了系統(tǒng)的內(nèi)聚性赐俗,減少了對(duì)外交互拉队,降低了系統(tǒng)的耦合性。
- 如果接口的粒度大小定義合理阻逮,能夠保證系統(tǒng)的穩(wěn)定性粱快;但是,如果定義過小叔扼,則會(huì)造成 接口數(shù)量過多事哭,使設(shè)計(jì)復(fù)雜化;如果定義太大瓜富,靈活性降低鳍咱,無法提供定制服務(wù),給整體項(xiàng)目帶來無法預(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)方法
在具體應(yīng)用接口隔離原則時(shí),應(yīng)該根據(jù)以下幾個(gè)規(guī)則來衡量:
- 接口盡量小椎眯,但是要有限度挠将。一個(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ì)外交互竞端。使接口用最少的方法去完成最多的事情屎即。
迪米特法則
迪米特法則的定義
迪米特法則( Law of Demeter,LoD )又叫作最少知識(shí)原則( Least Knowledge Principle, LKP ), 產(chǎn)生于 1987 年美國東北大學(xué)( Northeastern University )的一個(gè)名為迪米特( Demeter )的研究項(xiàng)目事富,由伊恩·荷蘭( Ian Holland )提出 技俐, 被 UML 創(chuàng)始者之一的布奇( Booch )普及,后來又因?yàn)樵诮?jīng)典著作《程序員修煉之道》提及而廣為人知统台。
迪米特法則的定義是:只與你的直接朋友交談雕擂,不跟“陌生人”說話。其含義是:如果兩個(gè)軟件實(shí)體無須直接通信贱勃,那么就不應(yīng)當(dāng)發(fā)生直接的相互調(diào)用捂刺,可以通過第三方轉(zhuǎn)發(fā)該調(diào)用。其目的是降低類之間的相合度募寨,提高模塊的相對(duì)獨(dú)立性族展。
迪米特法則中的 “朋友” 是指:當(dāng)前對(duì)象本身、當(dāng)前對(duì)象的成員對(duì)象拔鹰、當(dāng)前對(duì)象所創(chuàng)建的對(duì)象仪缸、當(dāng)前對(duì)象的方法參數(shù)等,這些對(duì)象同當(dāng)前對(duì)象存在關(guān)聯(lián)列肢、聚合或組合關(guān)系恰画,可以直接訪問這些對(duì)象的方法。
迪米特法則的優(yōu)點(diǎn)
迪米特法則要求限制軟件實(shí)體之間通信的寬度和深度瓷马,正確使用迪米特法則將有以下兩個(gè)優(yōu)點(diǎn):
- 降低了類之間的相合度拴还,提高了模塊的相對(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)方法
從迪米特法則的定義和特點(diǎn)可知韧献,它強(qiáng)調(diào)以下兩點(diǎn):從依賴者的角度來說末患,只依賴應(yīng)該依賴的對(duì)象。從被依賴者的角度說锤窑,只暴露應(yīng)該暴露的方法璧针。所以,在運(yùn)用迪米特法則時(shí)要注意以下 6 點(diǎ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ù)用原則( Composite Reuse Principle, CRP )又叫組合/聚合復(fù)用原則( Composition/Aggregate Reuse Principle, CARP。 它要求在軟件復(fù)用時(shí)瑞驱,要盡量先使用組合或者聚合等關(guān)聯(lián)關(guān)系來實(shí)現(xiàn)娘摔,其次才考慮使用繼承關(guān)系來實(shí)現(xiàn)。如果要使用繼承關(guān)系唤反,則必須嚴(yán)格遵循里氏代換原則凳寺。合成復(fù)用原則同里氏代換原則相輔相成的,兩者都是開閉原則的具體實(shí)現(xiàn)規(guī)范彤侍。
合成復(fù)用原則的重要性
通常類的復(fù)用分為繼承復(fù)用和合成復(fù)用兩種肠缨,繼承復(fù)用雖然有簡單和易實(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ù)用的靈活性漾橙。從父類繼承而來的實(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ì)象浙踢。
合成復(fù)用原則的實(shí)現(xiàn)方法
合成復(fù)用原則是通過將已有的對(duì)象納入新對(duì)象中,作為新對(duì)象的成員對(duì)象來實(shí)現(xiàn)的灿渴,新對(duì)象可 以調(diào)用己有對(duì)象的功能洛波,從而達(dá)到復(fù)用。
七種設(shè)計(jì)原則的要點(diǎn)
上面介紹了 7 種設(shè)計(jì)原則骚露,它們是軟件設(shè)計(jì)模式必須盡量遵循的原則蹬挤,各種原則要求的側(cè)重點(diǎn)不同。其中棘幸,開閉原則是總綱焰扳,它告訴我們要對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉够话;里氏替換原則告訴我們不要破壞繼承體系蓝翰;依賴倒置原則告訴我們要面向接口編程;單一職責(zé)原則告訴我們實(shí)現(xiàn)類要職責(zé)單一女嘲;接口隔離原則告訴我們?cè)谠O(shè)計(jì)接口的時(shí)候要精簡單一畜份;迪米特法則告訴我們要降低耦合度;合成復(fù)用原則告訴我們要優(yōu)先使用組合或者聚合關(guān)系復(fù)用欣尼,少用繼承關(guān)系復(fù)用爆雹。