不知不覺,在開發(fā)這條道路上摸爬打滾也有些年頭了,偶爾回頭看看以前寫的代碼,真可謂粗糙至極。當(dāng)然了,那時(shí)候還是小白,代碼寫得難看些情有可原,不過現(xiàn)在可不能再用以前的標(biāo)準(zhǔn)去衡量自己了,因此掌握一些高級(jí)架構(gòu)技巧是必須的,設(shè)計(jì)模式正是一個(gè)很好的敲門磚。 在我看來(lái),設(shè)計(jì)模式不僅僅只是一套模板,要想掌握設(shè)計(jì)模式并做到舉一反三,必須深入理解其中的思想,這個(gè)模式是為了解決什么問題?解決的思路是什么?代碼的實(shí)現(xiàn)又如何?如果問題細(xì)節(jié)發(fā)生了微小的變化又該如何處理?所以說思考很重要,不能死記硬背,一定要多想。 寫下這篇文章,是為了梳理自己的知識(shí)點(diǎn),做個(gè)記錄。如果有來(lái)人看到了,并且對(duì)你有幫助的話,我也會(huì)很開心,因?yàn)橹R(shí)是要傳播的,大家都樂于分享自己的見解,才能共同進(jìn)步。 設(shè)計(jì)模式的定義模式一詞起源于建筑業(yè),描述了解決問題的核心方法。通過這種方式,可以多次重用那些已有的解決方案,無(wú)須重復(fù)相同的工作。 模式可以應(yīng)用于不同的領(lǐng)域,軟件模式是將模式的一般概念應(yīng)用于軟件開發(fā)領(lǐng)域,可以被認(rèn)為是對(duì)軟件開發(fā)中某一特定問題的解法的某種統(tǒng)一表示。軟件模式并非僅限于設(shè)計(jì)模式,還包括架構(gòu)模式、分析模式和過程模式等,在軟件生存期的每一個(gè)階段都存在著一些被認(rèn)同的模式。 在軟件模式領(lǐng)域,目前研究最深入的是設(shè)計(jì)模式。設(shè)計(jì)模式是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié),使用這些設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。 設(shè)計(jì)模式的基本要素設(shè)計(jì)模式一般有如下幾個(gè)基本要素:模式名稱、問題、目的、解決方案、效果、實(shí)例代碼和其他相關(guān)設(shè)計(jì)模式,其中的關(guān)鍵元素包括以下四個(gè)方面: 模式名稱:通過一兩個(gè)詞來(lái)描述模式的問題、解決方案和效果,以更好地理解模式并方便開發(fā)人員之間的交流。 問題:描述了應(yīng)該在何時(shí)使用模式,它包含了設(shè)計(jì)中存在的問題以及問題存在的原因。有時(shí)候問題描述可能會(huì)包含使用該模式時(shí)必須滿足的一系列先決條件。 解決方案:描述了設(shè)計(jì)模式的組成部分,以及這些組成部分之間的相互關(guān)系,各自職責(zé)和協(xié)作方式。解決方案并不描述一個(gè)特定而具體的設(shè)計(jì)或?qū)崿F(xiàn),而是提供設(shè)計(jì)問題的抽象描述和怎樣用一個(gè)具有一般意義的元素組合(類或者對(duì)象)來(lái)解決這個(gè)問題。 效果:描述模式應(yīng)有的效果以及在使用模式時(shí)應(yīng)權(quán)衡的問題。效果主要包含模式的優(yōu)缺點(diǎn)分析,因此需要綜合考慮模式的效果。 設(shè)計(jì)模式的分類設(shè)計(jì)模式一般有兩種分類方式,一種是根據(jù)目的分類(模式是用來(lái)做什么的),另一種則是根據(jù)范圍分類(模式是用來(lái)處理類之間的關(guān)系還是處理對(duì)象之間的關(guān)系)。根據(jù)這兩種分類分別有如下兩張表供參考:
下面簡(jiǎn)單對(duì)二十三種設(shè)計(jì)模式進(jìn)行說明
軟件設(shè)計(jì)模式修煉 -- 簡(jiǎn)單工廠模式 以上就是設(shè)計(jì)模式的簡(jiǎn)單介紹,下面是一些補(bǔ)充知識(shí),如果已經(jīng)掌握了可以不看。這些知識(shí)雖然不屬于設(shè)計(jì)模式范疇,但對(duì)于我們理解設(shè)計(jì)模式有莫大的好處。 統(tǒng)一建模語(yǔ)言統(tǒng)一建模語(yǔ)言(UML)是一種可視化的標(biāo)準(zhǔn)建模語(yǔ)言,通過UML可以構(gòu)造軟件系統(tǒng)的藍(lán)圖。在設(shè)計(jì)模式中,使用UML來(lái)分析和設(shè)計(jì)每一個(gè)模式的結(jié)構(gòu),描述每一個(gè)模式實(shí)例,幫助我們深入理解設(shè)計(jì)模式。 比如要蓋一棟房子,需要先設(shè)計(jì)圖紙,設(shè)計(jì)圖紙就是一種設(shè)計(jì)語(yǔ)言,也就是模型語(yǔ)言。在一個(gè)現(xiàn)代化工程中,人們要溝通和協(xié)作,就必須使用標(biāo)準(zhǔn)的工業(yè)化設(shè)計(jì)語(yǔ)言,通過建模進(jìn)行描述,把所要設(shè)計(jì)的結(jié)構(gòu)和系統(tǒng)的行為聯(lián)系起來(lái),對(duì)系統(tǒng)的結(jié)構(gòu)進(jìn)行可視化控制。 UML 結(jié)構(gòu)UML 是由圖形符號(hào)表達(dá)的建模語(yǔ)言,其主要包括以下幾個(gè)部分: 視圖使用不同的視圖從不同角度來(lái)描述軟件系統(tǒng),包括: 用戶視圖:以用戶觀點(diǎn)表示系統(tǒng)的目標(biāo),它是所有視圖的核心,該視圖描述系統(tǒng)的需求 結(jié)構(gòu)視圖:表示系統(tǒng)的靜態(tài)行為和靜態(tài)元素,如包、類與對(duì)象,以及它們之間的關(guān)系 行為視圖:表示系統(tǒng)的動(dòng)態(tài)行為,描述組成元素如對(duì)象在系統(tǒng)運(yùn)行時(shí)的交互關(guān)系 實(shí)現(xiàn)視圖:表示系統(tǒng)中邏輯元素的分布,描述系統(tǒng)中物理文件以及它們之間的關(guān)系 環(huán)境視圖:表示系統(tǒng)中物理元素的分布,描述系統(tǒng)中硬件設(shè)備以及它們之間的關(guān)系 圖提供了十三種與上述五種視圖相對(duì)。在設(shè)計(jì)模式的學(xué)習(xí)中,重點(diǎn)關(guān)注類圖、順序圖和狀態(tài)圖即可。 用例圖:對(duì)應(yīng)用戶視圖。在用例圖中,使用用例來(lái)表示系統(tǒng)的功能需求,用例圖表示多個(gè)外部執(zhí)行者與系統(tǒng)用例之間以及用例與用例之間的關(guān)系。 類圖:對(duì)應(yīng)于結(jié)構(gòu)視圖。類圖使用類來(lái)描述系統(tǒng)的靜態(tài)結(jié)構(gòu),類圖包括類和它們之間的關(guān)系。 對(duì)象圖:對(duì)應(yīng)于結(jié)構(gòu)視圖。對(duì)象圖用于表示類的對(duì)象實(shí)例之間的關(guān)系。 包圖:對(duì)應(yīng)于結(jié)構(gòu)視圖。描述包與包之間的關(guān)系。 組合結(jié)構(gòu)圖:對(duì)應(yīng)于結(jié)構(gòu)視圖。表示一個(gè)類的內(nèi)部結(jié)構(gòu)。 狀態(tài)圖:對(duì)應(yīng)于行為視圖。描述一系列對(duì)象的狀態(tài)及狀態(tài)之間的轉(zhuǎn)換。 活動(dòng)圖:對(duì)應(yīng)于行為視圖。表示系統(tǒng)中各種活動(dòng)的次序。 順序圖:又稱時(shí)序圖或序列圖,對(duì)應(yīng)于行為視圖。表示對(duì)交互,重點(diǎn)表示對(duì)象之間發(fā)送消息的時(shí)間順序。 定時(shí)圖:對(duì)應(yīng)于行為視圖。定時(shí)圖采用一種帶數(shù)字刻度的時(shí)間軸來(lái)描述消息的順序,相比順序圖來(lái)說更加精確。 交互概覽圖:對(duì)應(yīng)于行為視圖??梢园呀换ジ庞[圖理解為細(xì)化的活動(dòng)圖,在其中的活動(dòng)都通過一些小型的順序圖來(lái)表示。 組件圖:又稱構(gòu)件圖,對(duì)應(yīng)于實(shí)現(xiàn)視圖。描述每個(gè)功能所在組件位置以及它們之間的位置。 部署圖:又稱實(shí)施圖,對(duì)應(yīng)于環(huán)境視圖。描述軟件中各個(gè)組件駐留的硬件位置以及這些硬件之間的交互關(guān)系。 模型元素模型元素包括事物以及事物之間的聯(lián)系。事物代表任何可以定義的東西,事物之間的關(guān)系把事物聯(lián)系在一起,組成有意義的結(jié)構(gòu)模式 通信機(jī)制為模型元素提供額外的注釋、修飾和語(yǔ)義。 面向?qū)ο笤O(shè)計(jì)原則面向?qū)ο笤O(shè)計(jì)原則是學(xué)習(xí)設(shè)計(jì)模式的基礎(chǔ),每一種設(shè)計(jì)模式都符合某一種或多種面向?qū)ο笤O(shè)計(jì)原則。在軟件開發(fā)中使用這些原則可以提高軟件的可維護(hù)性和可復(fù)用性,讓我們可以設(shè)計(jì)出更加靈活也更容易擴(kuò)展的軟件設(shè)計(jì),實(shí)現(xiàn)可維護(hù)性復(fù)用的目標(biāo)。 單一職責(zé)原則一個(gè)對(duì)象應(yīng)該只包含單一的職責(zé),并且該職責(zé)被完整地封裝在一個(gè)類中 一個(gè)類承擔(dān)的職責(zé)越多,被復(fù)用的可能性越小,并且相當(dāng)于將這些職責(zé)耦合在一起。因此需要將這些職責(zé)進(jìn)行分離,實(shí)現(xiàn)高內(nèi)聚、低耦合的指導(dǎo)方針。 開閉原則一個(gè)軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。也就是說在設(shè)計(jì)一個(gè)模塊,應(yīng)當(dāng)使這個(gè)模塊可以在不被修改的前提下被擴(kuò)展。 在開閉原則的定義中,軟件實(shí)體可以是一個(gè)軟件模塊、一個(gè)由多個(gè)類組成的局部結(jié)構(gòu)或一個(gè)類。 軟件的需求會(huì)隨著時(shí)間推移發(fā)生變化,如果軟件設(shè)計(jì)符合開閉原則,就可以在擴(kuò)展時(shí)無(wú)須修改現(xiàn)有代碼,保證穩(wěn)定性與延續(xù)性。 抽象化是滿足開閉原則的關(guān)鍵,通過定義一個(gè)相對(duì)穩(wěn)定的抽象層,將不同的實(shí)現(xiàn)行為在具體實(shí)現(xiàn)層中實(shí)現(xiàn)。如果需要修改,無(wú)須改動(dòng)抽象層,只需增加新的實(shí)體類來(lái)實(shí)現(xiàn)新的業(yè)務(wù)功能即可。 里氏代換原則所有引用基類(父類)的地方必須能透明地使用其子類的對(duì)象。說白了就是:在軟件中如果能使用其基類對(duì)象,那么一定能使用其子類對(duì)象。把基類都替換成它的子類,程序不會(huì)產(chǎn)生任何錯(cuò)誤。但反過來(lái)則不成立,如果一個(gè)軟件實(shí)體使用的是一個(gè)子類,那么它不一定能使用基類。 里氏代換原則是實(shí)現(xiàn)開閉原則的重要方式之一,在程序中盡量使用基類類型來(lái)定義對(duì)象,而在運(yùn)行時(shí)再確定其子類類型,用子類對(duì)象來(lái)替代父類對(duì)象。 依賴倒轉(zhuǎn)原則高層模塊不應(yīng)該依賴低層模塊,它們都應(yīng)該依賴抽象。抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象。即代碼要依賴于抽象的類,而不依賴于具體的類,要針對(duì)接口編程,不要針對(duì)實(shí)現(xiàn)編程。 如果說開閉原則是面向?qū)ο笤O(shè)計(jì)的目標(biāo)的話,那么依賴倒轉(zhuǎn)原則就是面向?qū)ο笤O(shè)計(jì)的主要手段。下面介紹依賴倒轉(zhuǎn)原則中經(jīng)常提到的兩個(gè)概念。 類之間的耦合:在面向?qū)ο笙到y(tǒng)中,兩個(gè)類之間通??梢园l(fā)生三種不同的耦合關(guān)系(依賴關(guān)系) 1. 零耦合關(guān)系:兩個(gè)類之間沒有任何耦合關(guān)系 2. 具體耦合關(guān)系:兩個(gè)具體類之間存在一個(gè)類對(duì)另一個(gè)具體類實(shí)例的直接引用 3. 抽象耦合關(guān)系:發(fā)生在一個(gè)具體類和抽象類之間,也可以發(fā)生在兩個(gè)抽象類之間。依賴倒轉(zhuǎn)原則要求客戶端依賴于抽象耦合。 依賴注入:簡(jiǎn)單來(lái)說,依賴注入就是將一個(gè)類的對(duì)象傳入另一個(gè)類,注入時(shí)應(yīng)該注入父類對(duì)象,而在程序運(yùn)行時(shí)再通過子類對(duì)象來(lái)覆蓋父類對(duì)象。依賴注入有三種方式 1. 構(gòu)造注入:通過構(gòu)造函數(shù)注入實(shí)例變量 2. 設(shè)值注入:通過Setter方法注入實(shí)例變量 3. 接口注入:通過接口方法注入實(shí)例變量 接口隔離原則一旦一個(gè)接口太大,則需要將它分割成一些更小的接口,使用該接口的客戶端僅需知道與之相關(guān)的方法即可。 這里的接口往往有兩種不同的含義: 一種是指一個(gè)類型所具有的方法的特征的集合,僅僅是邏輯上的概念,接口的劃分將直接帶來(lái)類型的劃分。此時(shí)可以把接口理解成角色,一個(gè)接口只代表一個(gè)角色,每個(gè)角色都有它特有的一個(gè)接口,此時(shí)這個(gè)原則叫做角色隔離原則。 另一種是指接口僅僅提高客戶端需要的行為,即所需的方法。接口應(yīng)該盡量細(xì)化,接口中的方法進(jìn)來(lái)少,每個(gè)接口只包含一個(gè)客戶端所需的角色。 合成復(fù)用原則盡量使用組合對(duì)象,而不是繼承來(lái)達(dá)到復(fù)用的目的。通俗來(lái)說,合成復(fù)用原則就是指一個(gè)新的對(duì)象里通過關(guān)聯(lián)關(guān)系(包括組合關(guān)系和聚合關(guān)系)來(lái)使用一些已有對(duì)象,使之成為新對(duì)象的一部分;新對(duì)象通過委派調(diào)用已有對(duì)象的方法達(dá)到復(fù)用已有功能的目的。 通過繼承來(lái)實(shí)現(xiàn)復(fù)用很簡(jiǎn)單,子類可以覆蓋父類方法,易于擴(kuò)展。但會(huì)破壞系統(tǒng)的封裝性,因?yàn)槔^承會(huì)將基類的實(shí)現(xiàn)細(xì)節(jié)暴露給子類,這種復(fù)用又稱為“白箱復(fù)用”。 通過組合/聚合來(lái)復(fù)用是將一個(gè)類的對(duì)象作為另一個(gè)類的對(duì)象的一部分。新對(duì)象可以調(diào)用已有對(duì)象的功能,這種復(fù)用又稱為“黑箱復(fù)用”。 迪米特法則指一個(gè)軟件實(shí)體應(yīng)盡可能少的與其他實(shí)體發(fā)生相互作用。當(dāng)一個(gè)模塊修改時(shí),就會(huì)盡量少的影響其他模塊,這是對(duì)軟件實(shí)體之間通信的限制,它要求軟件實(shí)體之間通信的寬度和深度。 在迪米特法則中,對(duì)于一個(gè)對(duì)象,其朋友包括以下幾類: 當(dāng)前對(duì)象本身(this) 以參數(shù)形式傳入到當(dāng)前對(duì)象方法中的對(duì)象 當(dāng)前對(duì)象的成員對(duì)象 如果當(dāng)前對(duì)象的成員對(duì)象是一個(gè)集合,那么集合中的元素也都是朋友 當(dāng)前對(duì)象所創(chuàng)建的對(duì)象 任何對(duì)象如果滿足上面的條件之一,就是當(dāng)前對(duì)象的“朋友”,否則就是“陌生人”。 狹義的迪米特法則:如果兩個(gè)類之間不必彼此通信,那么這兩個(gè)類就不應(yīng)當(dāng)發(fā)生直接的相互作用。如果其中一個(gè)類需要調(diào)用另一個(gè)類的某一個(gè)方法的話,可以通過第三者轉(zhuǎn)發(fā)這個(gè)調(diào)用。狹義的迪米特法則可以降低類之間的耦合,但也會(huì)造成系統(tǒng)不同模塊之間通信效率降低,使得系統(tǒng)的不同模塊之間不容易協(xié)調(diào)。 廣義的迪米特法則:指對(duì)象之間的信息流量、流向以及信息的影響的控制,主要是對(duì)信息隱藏的控制。信息的隱藏可以使各個(gè)子系統(tǒng)之間脫耦,每一個(gè)模塊不依賴于其他模塊存在,因此每一個(gè)模塊都可以獨(dú)立地在其他地方使用。 |
|
來(lái)自: 新進(jìn)小設(shè)計(jì) > 《待分類》