日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

设计模式实践及总结

發(fā)布時(shí)間:2024/7/5 asp.net 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 设计模式实践及总结 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、設(shè)計(jì)模式概念及設(shè)計(jì)原則

? ? ? ?記得剛開始學(xué)編程的時(shí)候就看過設(shè)計(jì)模式相關(guān)的書籍,雖然當(dāng)時(shí)有很多地方都不理解,但是建立了早期對(duì)架構(gòu)設(shè)計(jì)的意識(shí),讓后面的學(xué)習(xí)和工作中受益匪淺,最近兩年也一直在做架構(gòu)設(shè)計(jì)方面的工作,解開了之前很多的困惑,也形成了一些自己的思想,我需要把自己零散的想法系統(tǒng)的整理出來,如果能對(duì)大家有幫助當(dāng)然更好了。為什么選擇設(shè)計(jì)模式?因?yàn)榧軜?gòu)設(shè)計(jì)是一個(gè)很寬泛甚至對(duì)于有些人是一個(gè)很空虛的領(lǐng)域,設(shè)計(jì)模式的好處就在早就已經(jīng)有些很成熟被大家認(rèn)可的模式。既然已經(jīng)有了很成熟的模式我為什么還要重復(fù)造輪子呢?目前網(wǎng)上很多關(guān)于設(shè)計(jì)模式的文章都是講解各個(gè)模式的規(guī)則、目的,很少有直接應(yīng)用到實(shí)際工程的例子,所以我在設(shè)計(jì)模式后面加了個(gè)最佳實(shí)踐,目的就是通過工程實(shí)踐把自己在架構(gòu)設(shè)計(jì)方面的積累轉(zhuǎn)換成大家容易理解和熟悉的設(shè)計(jì)模式來表達(dá)出來

1.1、面向?qū)ο罅笤O(shè)計(jì)原則

(1)、單一職責(zé)原則(Single Responsibility Principle,簡(jiǎn)稱SRP)

? ? ? ?就一個(gè)類而言,應(yīng)該僅有一個(gè)引起它變化的原因。通俗的說,即一個(gè)類只負(fù)責(zé)一項(xiàng)職責(zé)。這是一個(gè)備受爭(zhēng)議卻又及其重要的原則,因?yàn)閱我宦氊?zé)的劃分界限并不是總是那么清晰,很多時(shí)候都是需要靠個(gè)人經(jīng)驗(yàn)來界定,如何劃分一個(gè)類、一個(gè)函數(shù)的職責(zé),每個(gè)人都有自己的看法,這需要根據(jù)個(gè)人經(jīng)驗(yàn)、具體的業(yè)務(wù)邏輯而定。但是它也有一些基本的指導(dǎo)原則,例如兩個(gè)完全不一樣的功能就不應(yīng)該放在一個(gè)類中。

(2)、開閉原則(Open Close Principle,簡(jiǎn)稱OCP)

? ? ? ?對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉開閉原則是讓程序更穩(wěn)定、更靈活的一個(gè)基本保證。程序中的對(duì)象(類、模塊、函數(shù)等)應(yīng)該對(duì)于擴(kuò)展是開放的,但是,對(duì)于修改是封閉的,在軟件的生命周期內(nèi),因?yàn)樽兓⑸?jí)和維護(hù)等原因需要對(duì)軟件原有代碼進(jìn)行修改時(shí),可能會(huì)將錯(cuò)誤引入原本已經(jīng)經(jīng)過測(cè)試的舊代碼中,破壞原有系統(tǒng)。因此,當(dāng)軟件需要變化時(shí),我們應(yīng)該盡量通過擴(kuò)展的方式來實(shí)現(xiàn)變化,而不是通過修改已有的代碼。

(3)、接口隔離原則(InterfaceSegregation Principles,簡(jiǎn)稱ISP)

? ? ? ?客戶端不應(yīng)該依賴它不需要的接口;一個(gè)類對(duì)另一個(gè)類的依賴應(yīng)該建立在最小的接口上。為依賴接口的類定制服務(wù),只暴露給調(diào)用的類它需要的方法,它不需要的方法則隱藏起來,只有專注地為一個(gè)模塊提供定制服務(wù),才能建立最小的依賴關(guān)系,提高內(nèi)聚,減少對(duì)外交互,使接口用最少的方法去完成最多的事情。接口盡量小,但是要有限度。對(duì)接口進(jìn)行細(xì)化可以提高程序設(shè)計(jì)靈活性是不掙的事實(shí),但是如果過小,則會(huì)造成接口數(shù)量過多,使設(shè)計(jì)復(fù)雜化,所以一定要適度。

(4)、里氏替換原則(Liskov Substitution Principle,簡(jiǎn)稱LSP)

? ? ? ?所有引用基類的地方必須能透明地使用其子類的對(duì)象。面向?qū)ο蟮恼Z言的三大特點(diǎn)是繼承、封裝、多態(tài),里氏替換原則就是依賴于繼承、多態(tài)這兩大特性里氏替換原則簡(jiǎn)單來說就是,所有引用基類的地方必須能透明地使用其子類的對(duì)象。通俗點(diǎn)講,只要父類能出現(xiàn)的地方子類就可以出現(xiàn),而且替換為子類也不會(huì)產(chǎn)生任何錯(cuò)誤或異常,使用者可能根本就不需要知道是父類還是子類。但是反過來就不行了,有子類出現(xiàn)的地方,父類未必就能適應(yīng)。說了那么多,其實(shí)最終總結(jié)就兩個(gè)字:抽象。

(5)、依賴倒置原則(Dependence Inversion Principle,簡(jiǎn)稱DIP)

? ? ? ?依賴反轉(zhuǎn)原則指代了一種特定的解耦形式,使得高層次的模塊不依賴于低層次的模塊的實(shí)現(xiàn)細(xì)節(jié)的目的,依賴模塊被顛倒了。這種表達(dá)真的讓人很難理解,簡(jiǎn)單點(diǎn):依賴倒置原則在 Java 語言中的表現(xiàn)就是:模塊間通過接口依賴,實(shí)現(xiàn)類之間不發(fā)生直接的依賴關(guān)系。再簡(jiǎn)單點(diǎn):面向接口編程,或者說是面向抽象編程

(6)、迪米特原則(Law of Demeter,簡(jiǎn)稱LOD)

? ? ? ?也稱為最少知識(shí)原則(Least Knowledge Principle):一個(gè)對(duì)象應(yīng)該對(duì)其他對(duì)象有最少的了解,也就是關(guān)于如何松耦合,一個(gè)類應(yīng)該對(duì)自己需要耦合或調(diào)用的類知道得最少,類的內(nèi)部如何實(shí)現(xiàn)、如何復(fù)雜都與調(diào)用者或者依賴者沒關(guān)系,調(diào)用者或者依賴者只需要知道他需要的方法即可,其他的我一概不關(guān)心。類與類之間的關(guān)系越密切,耦合度越大,當(dāng)一個(gè)類發(fā)生改變時(shí),對(duì)另一個(gè)類的影響也越大。

二、設(shè)計(jì)模式實(shí)踐及總結(jié)

2.1、簡(jiǎn)單工廠模式

? ? ? ?簡(jiǎn)單工廠模式 又稱為 靜態(tài)工廠模式
? ? ? ?模式場(chǎng)景:在一個(gè)披薩店中,要根據(jù)不同客戶的口味,生產(chǎn)不同的披薩,如素食披薩、希臘披薩等披薩。
? ? ? ?凡是看到一個(gè)工廠Factory,然后一個(gè)靜態(tài)方法,靜態(tài)方法一個(gè)參數(shù),那么很可能就是用到了 簡(jiǎn)單工廠 模式。

2.2、工廠方法模式

? ? ? ?client不需要知道具體產(chǎn)品,只需要知道具體工廠 即可。
? ? ? ?在披薩實(shí)例中,如果我想根據(jù)地域的不同生產(chǎn)出不同口味的披薩,如紐約口味披薩,芝加哥口味披薩。如果利用簡(jiǎn)單工廠模式,我們需要兩個(gè)不同的工廠,NYPizzaFactory、ChicagoPizzaFactory。在該地域中有很多的披薩店,他們并不想依照總店的制作流程來生成披薩,而是希望采用他們自己的制作流程。這個(gè)時(shí)候如果還使用簡(jiǎn)單工廠模式,因?yàn)楹?jiǎn)單工廠模式是將披薩的制作流程完全承包了。那么怎么辦?
? ? ? ?這樣解決:將披薩的制作方法交給各個(gè)披薩店完成,但是他們只能提供制作完成的披薩,披薩的訂單處理仍然要交給披薩工廠去做。也就是說,我們將createPizza()方法放回到PizzaStore中,其他的部分還是保持不變。
? ? ? ?示例有:日志記錄器
? ? ? ?凡是看到AbstractProduct、AbstractFactory、ConcretetFactory ,而且AbstractFactory 可以只能生產(chǎn)一個(gè)產(chǎn)品, 很可能就是用到了 工廠方法 模式。?

2.3、抽象工廠模式

? ? ? ?依然是披薩店。為了要保證每家加盟店都能夠生產(chǎn)高質(zhì)量的披薩,防止使用劣質(zhì)的原料,我們打算建造一家生產(chǎn)原料的工廠,并將原料運(yùn)送到各家加盟店。但是加盟店都位于不同的區(qū)域,比如紐約、芝加哥。紐約使用一組原料,芝加哥使用另一種原料。在這里我們可以這樣理解,這些不同的區(qū)域組成了原料家族,每個(gè)區(qū)域?qū)崿F(xiàn)了一個(gè)完整的原料家族。
? ? ? ?各個(gè)區(qū)域的加盟店的同一款產(chǎn)品是一個(gè)維度,是產(chǎn)品 等級(jí)結(jié)構(gòu)
? ? ? ?某個(gè)區(qū)域的加盟店的所有款產(chǎn)品是一個(gè)維度,是產(chǎn)品 族。
? ? ? ?抽象工廠類是不會(huì)涉及 加盟店的,抽象產(chǎn)品類的所有產(chǎn)品構(gòu)成 產(chǎn)品族。
? ? ? ?加盟店是具體的工廠類,是對(duì)抽象工廠類的實(shí)現(xiàn)。
? ? ? ?凡是看到AbstractProduct、AbstractFactory、ConcretetFactory ,而且AbstractFactory 可以生產(chǎn)多個(gè)產(chǎn)品, 很可能就是用到了 抽象工廠 模式。?

2.4、建造者模式

? ? ? ?建造者模式構(gòu)建復(fù)雜對(duì)象就像造汽車一樣,是一個(gè)一個(gè)組件一個(gè)一個(gè)步驟創(chuàng)建出來的,它允許用戶通過制定的對(duì)象類型和內(nèi)容來創(chuàng)建他們,但是用戶并不需要知道這個(gè)復(fù)雜對(duì)象是如何構(gòu)建的,它只需要明白通過這樣做我可以得到一個(gè)完整的復(fù)雜對(duì)象實(shí)例。
KFC里面一般都有好幾種可供客戶選擇的套餐,它可以根據(jù)客戶所點(diǎn)的套餐,然后在后面做這些套餐,返回給客戶的事一個(gè)完整的、美好的套餐。(構(gòu)造過程抽象統(tǒng)一為buildFood,buildDrink)
? ? ? ?示例有:游戲角色設(shè)計(jì)
? ? ? ?凡是看到出現(xiàn)以Director、Builder結(jié)尾、或包含build、 construct方法 的類, 很可能就是用到了 建造者模式。

2.5、原型模式

? ? ? ?Ctrl+C、Ctrl+V、克隆、復(fù)制簡(jiǎn)歷、復(fù)制Xxx。。。
? ? ? ?示例有:大同小異的工作周報(bào)、帶附件的周報(bào)
? ? ? ?凡是看到出現(xiàn)以Prototype結(jié)尾、或包含clone、copy方法 的類, 很可能就是用到了 原型模式。

2.6、單例模式

? ? ? ?如果制造出多個(gè)實(shí)例,會(huì)導(dǎo)致很多問題產(chǎn)生的情況。
? ? ? ?通常是重量級(jí)的類,比如tomcat的ServletContext,Hibernate的SessionFactory,Spring的BeanFactory,通常只有一個(gè)
? ? ? ?單例模式一般通過靜態(tài)的實(shí)例變量來實(shí)現(xiàn),可以想象的是,如果這個(gè)全局唯一的 靜態(tài)的實(shí)例變量 能夠保證其創(chuàng)建的 其他Subject(比如Bean)也是只有一個(gè), 那么那些Subject 也是單例的, 盡量“那些Subject” 本身并本身 單例模式~ 比如, 我們Spring 容器中的單例的Bean。 單例的Bean 并不是設(shè)計(jì)模式中單例模式, ?只是其scope是 Spring 容器唯一。這個(gè)是兩碼事,大家應(yīng)該還? ? ? ?是能夠區(qū)分清楚的吧!
? ? ? ?Spring 容器何保證,其單例的Bean,每次獲取得到的 都是同一個(gè)? 一般,我們的通過緩存, 即緩存到內(nèi)存。
? ? ? ?通過“ ? Spring 容器中的單例的BeanSpring 容器中的單例的Bean ? ”這樣的方式, 我們實(shí)際上可以實(shí)現(xiàn)一個(gè) 單例鏈或 單例實(shí)例鏈: 最開始的某些對(duì)象是靜態(tài)單例的,其創(chuàng)建的bean 不是單例,不是靜態(tài),卻是唯一的,bean 可以?創(chuàng)建其他 “ ?bean 不是單例,不是靜態(tài),卻是唯一的 ”, 過程反復(fù), 就形成了一個(gè)鏈條。
? ? ? ?當(dāng)然我們說全局, 這個(gè)局有多大,仍然是個(gè)相對(duì)的概念。
? ? ? ?示例有:太多
? ? ? ?凡是看到 Singleton getSingleton, 很可能就是用到了 單例模式。 ?雖然實(shí)踐中 不一定使用 Singleton 這個(gè)詞, 但這個(gè)是常見的。是良好的實(shí)際。?

2.7、適配器模式

? ? ? ?我們工作電壓11V的電腦,需要在 220V的 輸電電壓下 工作, 我們就需要 電源適配器; 機(jī)器人想要模擬人的操作,那么也需要進(jìn)行 某些適配工作。
? ? ? ?示例有:沒有源碼的算法庫
? ? ? ?Target 雖然常見,但是我們一般不會(huì)使用這個(gè)詞,而是直接使用我們實(shí)際的類的名稱。凡是看到出現(xiàn)以Adapter、Adaptee結(jié)尾、或包含request,specialRequest 方法 的類, 很可能就是用到了 適配器 模式。盡管如此,我們實(shí)際中可能不會(huì)使用 request,specialRequest 這樣的詞, 而是直接、具體的 接口名字。

2.8、橋接模式

? ? ? ?假設(shè)圖形類有兩個(gè)關(guān)鍵屬性: 形狀、顏色。我們有 正方形、長(zhǎng)方形、圓形,有三種顏色:白色、灰色、黑色,那么我們可以畫出3*3=9中圖形。 那么 我們是不是就需要九個(gè) class類呢? 不需要的,通過橋接模式,我們只需要 3+3 = 6 個(gè)類。
可以想象,如果形狀、顏色 更多,那么 橋接模式 就非常有效的減少了類的數(shù)量。
? ? ? ?橋接模式 好像和 裝飾模式有異曲同工之妙,它們都可以有效的減少了類的數(shù)量, 防止類數(shù)量爆炸。 但是這里的例子中,裝飾模式是不合適的, 因?yàn)?形狀、顏色 是兩個(gè)獨(dú)立的屬性,沒有任何相關(guān)關(guān)系的。
? ? ? ?橋接模式 是對(duì) 不同屬性, 從不同維度的 拆分。屬性之間 僅僅是一個(gè) 聚合關(guān)系
? ? ? ?裝飾模式 是對(duì) 不同行為,圍繞某個(gè)主要行為 進(jìn)行 裝飾。需要有繼承or實(shí)現(xiàn)關(guān)系
?? ? ? ?示例有:跨平臺(tái)圖像瀏覽系統(tǒng)
? ? ? ?凡是看到出現(xiàn)以RefinedAbstraction、Implementor結(jié)尾 的類, 很可能就是用到了 橋接模式。 雖然實(shí)際中 很可能不會(huì)使用 RefinedAbstraction、Implementor 這樣的詞來命名我們的類名,但是, 仍然可以做一個(gè)判斷。

2.9、組合模式

? ? ? ?凡是涉及文件系統(tǒng)的瀏覽遍歷、操作等的, 比如 殺毒軟件對(duì) 文件系統(tǒng)進(jìn)行殺毒。
? ? ? ?語法樹,比如XML,HTML,JSON 常常存在 “容器” 元素, 就很適合 組合模式 ?。比如 HTML 語法樹,我們可以把 div 當(dāng)做一個(gè) 容器,div 可以嵌套各種子元素。
? ? ? ?示例有:Configuration、Bean、Component
? ? ? ?凡是看到出現(xiàn)以Composite、Leaf、combination、assembly、group結(jié)尾、或包含filter、 handle、intercept 方法 以及 add、remove、getChild 方法 的類, 很可能就是用到了 裝飾器模式。?

2.10、裝飾器模式

? ? ? ?需要?jiǎng)討B(tài)地給一個(gè)對(duì)象增加功能,這些功能也可以動(dòng)態(tài)地被撤銷。 ?當(dāng)不能采用繼承的方式對(duì)系統(tǒng)進(jìn)行擴(kuò)充或者采用繼承不利于系統(tǒng)擴(kuò)展和維護(hù)時(shí)。
? ? ? ?裝飾者模式的關(guān)鍵詞, 一定是“動(dòng)態(tài)、靈活”, 通過繼承,我們可以做很多事情,但是顯得十分臃腫,十分不動(dòng)態(tài),類數(shù)量(m*n)爆炸。裝飾者模式可以避免這些, 將類數(shù)量 變化 m + n
? ? ? ?其實(shí),裝飾模式和適配器模式都是“包裝模式(Wrapper Pattern)”。 另外代理模式,好像也有包裝 功能,但是要求、側(cè)重點(diǎn)是不同的。
? ? ? ?示例有:圖形界面構(gòu)件庫
? ? ? ?凡是看到出現(xiàn)以Decorator、Filter、Interceptor 、Wrapper 結(jié)尾、或包含filter、 handle、intercept 方法 的類, 很可能就是用到了 裝飾器模式。

2.11、外觀/門面模式

? ? ? ?非常籠統(tǒng)而寬泛的模式
?? ? ? ?示例有:B/S系統(tǒng)的首頁等等
? ? ? ?凡是看到出現(xiàn)以Facade、System、Manager 結(jié)尾 的類, 很可能就是用到了 外觀/門面模式。 沒錯(cuò),這里有個(gè)Manager ,Manager 是一個(gè)范疇很大的詞。

2.12、享元模式

? ? ? ?其實(shí)就是 對(duì)一系列類似的 對(duì)象, 實(shí)現(xiàn)了 單例模式, 然后統(tǒng)一管理。
? ? ? ?示例有:ThreadLocal,Redis緩存。http、redis、mq、kafka、String常量池、數(shù)據(jù)庫連接池、緩沖池
? ? ? ?凡是看到出現(xiàn)以Flyweight 結(jié)尾 的類, 很可能就是用到了享元模式。實(shí)踐中,我們可能不會(huì)使用Flyweight這樣的詞,而是具體的 “ 元 ” 的類名, 而判斷是否是 享元, 關(guān)鍵是 判斷是否有一個(gè) map 存在, 其 get 方法是否會(huì)判斷“元” 是否已經(jīng)存在,是否包含了 put 操作。?

2.13、代理模式

? ? ? ?web 代理服務(wù)器、Nginx反向代理,JDK動(dòng)態(tài)代理,CGlib 動(dòng)態(tài)代理
? ? ? ?1、 遠(yuǎn)程代理:為一個(gè)對(duì)象在不同的地址空間提供局部代表。這樣可以隱藏一個(gè)對(duì)象存在于不同地址空間的事實(shí)。
? ? ? ?2、 虛擬代理:通過使用過一個(gè)小的對(duì)象代理一個(gè)大對(duì)象。這樣就可以減少系統(tǒng)的開銷。
? ? ? ?3、 保護(hù)代理:用來控制對(duì)真實(shí)對(duì)象的訪問權(quán)限。
? ? ? ?示例有:收費(fèi)商務(wù)信息查詢系統(tǒng)
? ? ? ?凡是以Proxy 結(jié)尾,或看到出現(xiàn)包含preRequest,postRequest 等 preXxx、postXxx 方法 的類,或看到 InvocationHandler, 很可能就是用到了代理模式。

2.14、職責(zé)鏈模式

? ? ? ?凡是那些涉及 不同等級(jí)層次的 操作、流程,不同等級(jí)有不同權(quán)限、功能,或需要 層層審批。那么就適合。
? ? ? ?示例有:采購單的分級(jí)審批、請(qǐng)假流程、報(bào)銷審批流程。。。
? ? ? ?凡是看到出現(xiàn)以Chain、pipeline 結(jié)尾、或包含handler,handleRequest 方法 的類, 很可能就是用到了責(zé)任鏈模式。

2.15、命令模式

? ? ? ?Invoker (調(diào)用者)本來可以直接調(diào)用Receiver(接收者), 但是Invoker 覺得麻煩,不想、不需或不能 管太多 ,那么我們引入一個(gè) Command 中間層,那么 就實(shí)現(xiàn)了解耦
? ? ? ?一些場(chǎng)景:控制面板、遙控器
? ? ? ?示例有:自定義功能鍵、撤銷操作、宏命令
? ? ? ?凡是看到出現(xiàn)以Command、Order 、Invoker、Receiver 結(jié)尾、或包含execute、call、action 方法 的類, 很可能就是用到了 命令模式。

2.16、解釋器模式

? ? ? ?語法分析解釋權(quán)、抽象語法樹,翻譯機(jī)。對(duì)不懂的外國語進(jìn)行 翻譯。等等
? ? ? ?示例有:機(jī)器人控制程序
? ? ? ?凡是看到出現(xiàn)以Expression/ translate/ interpret 結(jié)尾、或包含 translate/ interpret 方法 的類, 很可能就是用到了 解釋器模式。

2.17、迭代器模式

? ? ? ?Aggregate和 Iterator 分離。為什么需要分離? Iterator 不需要知道Aggregate的數(shù)據(jù)是怎么來的, 可以按照需要的 方式進(jìn)行遍歷。 比如對(duì)電視機(jī)的各個(gè)有限電視臺(tái)的遍歷,我們可以 按照 各個(gè)省、地方電視臺(tái)的順序,一個(gè)省的所有電視臺(tái)遍歷完了之后,再其他省; 也可以按照 先遍歷所有省的 娛樂頻道,然后遍歷所有省的 經(jīng)濟(jì)頻道,然后。。
HaspMap的 迭代器。
?? ? ? 示例有:JDK內(nèi)置迭代器、銷售管理系統(tǒng)中數(shù)據(jù)的遍歷
? ? ? ?凡是看到出現(xiàn)以Iterator、Loop 結(jié)尾、或包含hasNext,next,hasMore方法 的類, 很可能就是用到了 迭代器模式。

2.18、中介者模式

? ? ? ?中介,就是我們平常所理解的 中介。適合某些 雙方/多方 不宜 直接對(duì)話的情況。 中介者, 當(dāng)然,需要一定的 權(quán)威性、權(quán)力、公信度。
? ? ? ?同事之間 雖然可以直接1對(duì)1,溝通,但某些時(shí)刻需要通過部門負(fù)責(zé)人來 中介、協(xié)調(diào)。同學(xué)之間 需要通過 輔導(dǎo)員、班主任來溝通、 統(tǒng)一領(lǐng)導(dǎo)、指揮。男方和 女方 通過婚介所 進(jìn)行聯(lián)誼。 租房者與房屋所有者之間通過 某些 中介機(jī)構(gòu) 來交互、溝通。求職者和 用人企業(yè)之間 通過求職網(wǎng)站、獵頭 充當(dāng)中介。 國與國之間的關(guān)系異常復(fù)雜,聯(lián)合國 可以算是一個(gè) 中介。等等
實(shí)際生活中,我們常常把 中介和 代理混為一談,因?yàn)橛袝r(shí)候確實(shí)是 很難區(qū)分,但是設(shè)計(jì)模式中,我們不為,因?yàn)?#xff0c;我們需要滿足uml 的限制,當(dāng)然,我們也不一定拘泥于 uml。 Agent 到底是代理 還是中介?討論這個(gè)問題沒有意義。
? ? ? ?示例有:協(xié)調(diào)者
? ? ? ?凡是以Mediator、Colleague、middleMan,Agent 結(jié)尾的類, 很可能就是用到了 中介 模式。當(dāng)然,colleague的語義比較窄, 我們可能并不會(huì)使用這個(gè)詞,而是其他類似的詞。比如 同窗,同僚,co-author,co-worker,counterparter 。

2.19、備忘錄模式

? ? ? ?某些對(duì)象,你想保存下來, 但是對(duì)象的的內(nèi)部狀態(tài)比較復(fù)雜, 你記不住, 不方便直接操作器狀態(tài), 這個(gè)時(shí)候,我們可以使用 備忘錄(Memento)把它,“錄”下來,以防“備忘”,
? ? ? ?但是呢,備忘錄模式的 備忘錄本身沒有備忘的 功能,備忘的功能 由 負(fù)責(zé)人(Caretaker) 提供。所以說,備忘錄模式 跟我們 實(shí)際生活 用到的 備忘錄, 其實(shí)并不對(duì)等。 如果,非要對(duì)應(yīng)起來的話,那么 “實(shí)際生活 用到的 備忘錄 ” 對(duì)應(yīng) 備忘錄模式的Caretaker,但是“ 實(shí)際生活 用到的 備忘錄 ” 并沒有 restore 功能, 這個(gè)需要人來做,相對(duì)于是 save、 restore 功能分離了。
? ? ? ?場(chǎng)景: 需要撤銷動(dòng)作的 對(duì)象
? ? ? ?示例有:游戲存檔
? ? ? ?Originator這個(gè)詞很少見,Mememto 也不多見,只要看到了它們,或者save 同時(shí) restore 這個(gè)關(guān)鍵字, 很可能就是用到了 備忘錄模式。

2.20、觀察者模式

? ? ? ?觀察者模式又稱為發(fā)布-訂閱模式。
? ? ? ?觀察者? 太多了。觀察? 太常見的動(dòng)作了!所以 觀察者模式 是我們時(shí)時(shí)刻刻都在用到的,只不過,用得太多,沒感覺了,向空氣一樣感覺不到它的存在了!比如吃飯,看飯下菜;你看電視,然后隨著劇情喜怒哀樂;開車根據(jù)路標(biāo)指示做不同的操作;觀察明天的天氣,看看去哪里玩 合適;觀察研究不同股票的表現(xiàn),決定買入還是賣出還是等待;隨心而動(dòng)、隨性而為。。
? ? ? ?jdk是有提供 Observeable,Listener、消息隊(duì)列MQ。。。
? ? ? ?使用觀察者模式,天然的 就將 被觀察目標(biāo) 和 觀察者 解耦了! 但是呢,我們實(shí)際軟件開發(fā)的過程中,并不是說 用眼睛觀察一下,看一下就完了(貌似只消耗了一些光子,沒有和 Subject產(chǎn)生 任何關(guān)系),并不是說 Subject和 Observer 完全沒有關(guān)系,Subject 是必須依賴Observer 的(一般來說,Subject對(duì)象 擁有 Observer 對(duì)象的集合)。
? ? ? ?另外,我們需要注意,實(shí)際軟件開發(fā)中 觀察者 是可以出現(xiàn)異常的(觀察到事件,但是處理發(fā)生了異常), 這個(gè)時(shí)候呢, 應(yīng)該觀察者Observer 是不應(yīng)該影響到 Subject 的繼續(xù)運(yùn)行的,也就是說 Observer 需要處理所有異常, 而不應(yīng)該 拋給Subject ?。
觀察者模式 和 監(jiān)聽模式 幾乎是一個(gè)意思。 觀察者 就是 監(jiān)聽器。
? ? ? ?觀察者模式 和 事件驅(qū)動(dòng) 幾乎可以認(rèn)為是 同義詞。觀察者模式 中雖然 沒有體現(xiàn)出來 事件, 但是 具體主題發(fā)生改變時(shí),會(huì)notify 所有的 監(jiān)聽者、觀察者, 給所有的觀察者發(fā)出通知, 這個(gè)通知 其實(shí)就是 可以認(rèn)為是一個(gè) 事件。
? ? ? ?示例有:XxxListener
? ? ? ?凡是看到出現(xiàn)以Event、Listener結(jié)尾、或包含notify、update、observe、onXxxEvent方法 的類, 很可能就是用到了 觀察者模式。

2.21、狀態(tài)模式

? ? ? ?狀態(tài)模式 主要是把 對(duì)象的 狀態(tài) 獨(dú)立了出來,成了 狀態(tài)類, 每個(gè)狀態(tài) 都需要處理當(dāng)前狀態(tài)下的 一些具體事情,對(duì)外表現(xiàn)不同的行為,所以 State 有一個(gè) handle 方法, 每個(gè)ConcreteState 需要實(shí)現(xiàn)它。
? ? ? ?狀態(tài)模式 的核心要義并不是 狀態(tài)類, 而是 不同狀態(tài)之間的切換。Context 發(fā)起狀態(tài)切換,ConcreteState 完成具體的操作。
酒店房間Room有預(yù)定book、取消預(yù)定unbook、入住checkIn(可繼續(xù)細(xì)分為住滿,未住滿)、單人狀態(tài)等待雙人拼房、更換房間、退房checkOut等 必要的接口操作,有 空閑、預(yù)定、入住 等狀態(tài), 不同狀態(tài) 對(duì) 客戶請(qǐng)求是不一樣的,空閑狀態(tài)是可以預(yù)定、直接入住的,但是不能退房。預(yù)定狀態(tài)可以 入住、更換房間、取消預(yù)定,但是不能退房,已入住狀態(tài) 不能再 預(yù)定、取消預(yù)定、入住, 只有一個(gè)退房操作。
? ? ? ?Context可以自己直接轉(zhuǎn)換狀態(tài),但一般來說是交給State 去handle。具體來說,Room可以提供一個(gè) setState 接口,或者提供 多個(gè)具體的接口:book,unbook, checkIn,checkOut等,顯然后者更加合理。
實(shí)際呢? 我看到使用更多的是Constants、Enum 這樣的常量、枚舉類,它們其實(shí)是可以轉(zhuǎn)換為狀態(tài)模式的。 ?而且如果 行為比較復(fù)雜, 改為 狀態(tài)模式 應(yīng)該會(huì)更好一些。
? ? ? ?狀態(tài)模式 是否 可以完全的 取代 枚舉類 ? 當(dāng)然是不能的,比如我一個(gè)很簡(jiǎn)單的東西, 一個(gè)星期有7天,分別是Monday、Tuesday、Wednesday、Thursday、Friday、Saturday、Sunday, 這樣簡(jiǎn)單的枚舉,并不涉及任何復(fù)雜的具體的 行為、操作, 用一個(gè)枚舉就蠻好的,星期幾一般不會(huì)用作為一個(gè)狀態(tài),不會(huì)影響對(duì)象的行為。沒必要狀態(tài)模式。春夏秋冬,東南西北,都不是狀態(tài)。
? ? ? ?狀態(tài)模式 關(guān)鍵是狀態(tài)的選取,狀態(tài)一定是影響對(duì)象 對(duì)請(qǐng)求的響應(yīng)的。關(guān)鍵要理解 狀態(tài)是否可以獨(dú)立出來,狀態(tài)改變對(duì) 對(duì)象行為的 影響。
? ? ? ?狀態(tài)模式 說白了就是 把一個(gè)很大的if else 語句塊,變成了 比較小的if else 語句塊,但是 if else 語句塊 仍然存在,不符合 開閉原則。
? ? ? ?示例有:銀行系統(tǒng)中的賬戶類設(shè)計(jì)
? ? ? ?凡是以State結(jié)尾的類, 很可能就是用到了 狀態(tài)模式。當(dāng)然,這個(gè)是不一定的,我們可能會(huì)使用諸如 Status、Way、Method、Operation 這樣的次。

2.22、策略模式

? ? ? ?策略模式關(guān)鍵是需要理解 策略。這里的策略,并不是說指揮三軍打仗的 謀略,也不一定要 國家頒布了 新的房地產(chǎn)發(fā)展規(guī)劃指南 才能算是策略。而是說 做一件事情的 不同的方式,方法。 比如我吃飯,可以拿筷子吃,也可以直接手抓著吃,可以拿盤子盛著,可以拿碗,可以拿杯,也可以直接拿鍋; 去韓國旅行,可以坐飛機(jī)、鐵路、公路,海路等等,都可以是策略。
當(dāng)然,我們還可以把策略理解為 算法。我需要排序一個(gè)數(shù)組,可以冒泡算法、可以選擇算法等等。 我們關(guān)注目的,只要目標(biāo)達(dá)成了,就好了,不同的策略 給與我們不同的選擇,讓我們 靈活切換。
? ? ? ?示例有:電影票打折方案
? ? ? ?凡是以Strategy結(jié)尾的類, 很可能就是用到了 策略模式。或者algorithm 結(jié)尾。

2.23、模板方法模式

? ? ? ?如果你做了很多類似的,有一定重復(fù)工作的事情 但又不完全相同的,比較固定的操作流程, 而且以后也還要經(jīng)常做,那么可以考慮 提取出來一個(gè)模板方法,把高層級(jí)的某些 操作順序、流程 固定化,然后 把具體的不同的工作 在實(shí)際操作的時(shí)候 去細(xì)化去完成,那么這就是 模板方法模式。
? ? ? ?模板方法模式 強(qiáng)調(diào) 模板。必須是能夠提取出來一個(gè)做事、操作的模板, 才比較合適。
? ? ? ?一些場(chǎng)景有:比如,每個(gè)人都要經(jīng)歷 出生-學(xué)校讀書-工作-退休-去世 等過程,這些基本是固定的, 但是具體的操作非常不一樣。 當(dāng)然這樣的例子 太寬泛了, 不容易進(jìn)行細(xì)致討論。
比如,很多人的每天就是 起床-洗漱-早餐-坐公交/地鐵去公司-工作-午餐/午休-工作-坐公交/地鐵回家-晚餐-休息-睡覺 的這樣的routine , 對(duì)這些人,我們可以套用一個(gè)模板(當(dāng)然,對(duì)于其他人,這個(gè)模板可能就不適用了)
? ? ? ?往細(xì)一點(diǎn)說,我們java 使用數(shù)據(jù)庫,都有固定的幾個(gè)步驟: 連接數(shù)據(jù)庫、獲取datasource、獲取connection、創(chuàng)建statement、執(zhí)行sql、獲取結(jié)果resultset、關(guān)閉connection,除了 執(zhí)行sql 按照具體情況很大不同之外,其他步驟基本是相同的,因?yàn)閟pring 為我們封裝了JDBCTemplate。等等。
? ? ? ?示例有:JDBCTemplat、銀行利息計(jì)算模塊
? ? ? ?凡是XxxTemplate這樣的 以Template結(jié)尾的類, 很可能就是用到了 模板方法模式。

2.24、訪問者模式

? ? ? ?現(xiàn)在 我們(作為游客,Vistor)去景區(qū)旅游。景區(qū)有很多景點(diǎn)(Element),每個(gè)景點(diǎn)呢需要收取不同的票價(jià)、有不同的景觀、有不同的接待(accept)方式,游客(Vistor)呢,可以選擇 任意一些景點(diǎn),然后進(jìn)行 游覽(visit)。我們可以都選擇獨(dú)立游或自駕游,但是這樣呢,景區(qū)會(huì)比較亂而 不好做規(guī)劃。我們可以選擇導(dǎo)游。導(dǎo)游((ObjectStructure))可以幫助我們完成這個(gè)過程。
? ? ? ?Element景點(diǎn)的一般操作是:制定門票價(jià)格、接受 游客 進(jìn)入游玩(accept,accept方法的參數(shù)正是 Visitor 游客)
? ? ? ?ConcreteElement具體景點(diǎn)的作用是:設(shè)置具體的 門票價(jià)格,提供各種游玩場(chǎng)所和設(shè)施,接受游玩。
? ? ? ?Vistor游客的一般操作是:買票、訪問(visit ,visit 方法的參數(shù)正是 Element景點(diǎn))某個(gè) / 某些 景點(diǎn) ... ;
? ? ? ?ConcreteVisitor具體游客的作用是:花實(shí)際的價(jià)錢買票,選擇具體的 景點(diǎn),而不是全部。
? ? ? ?ObjectStructure導(dǎo)游的作用是:對(duì)象結(jié)構(gòu),包含了一個(gè)景區(qū)List (提供add、remove接口,可以動(dòng)態(tài)增刪),能夠枚舉各個(gè)景點(diǎn),然后 同樣提供 accept 接待訪問的接口, 然后 遍歷 list 以供游客訪問景區(qū)。
? ? ? ?這樣,我們可以 方便的增加 景點(diǎn),和 游客。 好像沒有任何的問題。
? ? ? ?但是,uml 中 Vistor游客的訪問方法的參數(shù) 是具體景點(diǎn)ConcreteElement,而不是Element。可以認(rèn)為ConcreteElementA是 歌劇表演、B是山水、C是舞蹈魔術(shù) ,Vistor 做了這么一個(gè)限定,提供三個(gè)接口,任何游客可以訪問3個(gè)類型景點(diǎn)。 每個(gè)具體類型景點(diǎn) 需要標(biāo)明自己是類型,(比如 門口標(biāo)志 需要特定服裝才能進(jìn)入、僅限兒童進(jìn)入等等)也就是說,景區(qū),為了牟利,并不管你是 兒童還是老人,都可以給你推薦 兒童樂園。 景區(qū) 盡量讓游客把每個(gè)景點(diǎn)都至少玩一遍。
? ? ? ?Vistor游客也可以分類,比如兒童、年輕人、老人,兒童有兒童的游玩方式、年輕人、老人游玩方式都不同。
?? ? ? ?還可以這樣分類: A兒童景點(diǎn),B是年輕人景點(diǎn),C是老人景點(diǎn)。
? ? ? ?這個(gè)模式有一點(diǎn)不好的是, 不管Vistor是否愿意,它需要把所有具體的Element的訪問接口準(zhǔn)備好。當(dāng)然,這僅僅是準(zhǔn)備,并一定要實(shí)際的去訪問, 提供訪問的可能性。但這個(gè)是比較麻煩的,因?yàn)橛慰涂赡芨静恍枰ピL問它(不管怎么樣,景區(qū)還是要把 景點(diǎn) 推廣出去)。如果我們 增加了一個(gè)類型 景點(diǎn),比如驚險(xiǎn)刺激類的過山車,那么 所有的ConcreteElement都要做變化, 破壞了開閉原則。
? ? ? ?這個(gè)例子可能并不太好,實(shí)際情況,我們可以有那種不得不訪問的情況,比如 買房過程,一般來說,必須要去 房產(chǎn)銷售中心商談、去商品房的實(shí)際地點(diǎn)看看毛坯房、 去房管局登記 / 繳稅費(fèi) / 拿發(fā)票 等, 每一個(gè)步驟的接口 都是開放的, 買房者需要去準(zhǔn)備(去實(shí)現(xiàn)之),雖然不一定馬上就去做(不一定立即調(diào)用 各個(gè) visit 方法)。如果政府規(guī)定了買房必須去中國銀行 報(bào)備,那么 買房者還需要去準(zhǔn)備 一個(gè) 訪問 中國銀行的接口。
? ? ? ?另外,訪問者模式 的訪問,不一定的 訪問,也可以是 交互、。。
? ? ? ?示例有:OA系統(tǒng)中員工數(shù)據(jù)匯總
? ? ? ?凡是看到 Visit、ObjectStructure, 很可能就是用到了 訪問者方法模式。

總結(jié)

以上是生活随笔為你收集整理的设计模式实践及总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。