淺顯而精辟地解說(shuō)設(shè)計(jì)模式
什么是設(shè)計(jì)模式?
設(shè)計(jì)模式是對(duì)軟件設(shè)計(jì)中出現(xiàn)的典型問(wèn)題的常規(guī)解決方案。它們就像一個(gè)解決典型問(wèn)題的藍(lán)圖,您可以對(duì)其進(jìn)行定制。
我為什么要學(xué)習(xí)模式?
關(guān)于設(shè)計(jì)模式的好處是,它們是針對(duì)常見(jiàn)問(wèn)題的經(jīng)過(guò)嘗試和測(cè)試的解決方案。這使您能夠以有效的方式解決在程序中遇到的問(wèn)題,而不必重新發(fā)明輪子。如果您和您的團(tuán)隊(duì)成員了解模式,它可以幫助提高溝通的效率。
使用模式也有一些缺點(diǎn)。當(dāng)您了解不同的軟件模式時(shí),您可能會(huì)嘗試實(shí)現(xiàn)不需要或不是最佳解決方案的模式。另一個(gè)可能的缺點(diǎn)是試圖實(shí)現(xiàn)一個(gè)模式過(guò)于字面化,而沒(méi)有根據(jù)項(xiàng)目的上下文對(duì)其進(jìn)行定制。
模式分類
設(shè)計(jì)模式通常分為三類: 創(chuàng)建模式、結(jié)構(gòu)模式和行為模式。
創(chuàng)建模式描述了創(chuàng)建對(duì)象的方法,這些方法可以提高代碼重用性和靈活性。
結(jié)構(gòu)模式為如何將對(duì)象和類構(gòu)建成更大的結(jié)構(gòu)提供了模式,同時(shí)使它們具有適應(yīng)性和高效性。
行為模式描述了用于有效通信和對(duì)象之間責(zé)任委托的模式。
讓我們來(lái)探索一些更常見(jiàn)的軟件設(shè)計(jì)模式。
工廠法
Factory 方法解決了創(chuàng)建對(duì)象時(shí)不必指定所創(chuàng)建的確切類的問(wèn)題。超類定義了一個(gè)創(chuàng)建對(duì)象的接口,子類實(shí)現(xiàn)了創(chuàng)建對(duì)象的特定邏輯。
例如,可以引入一個(gè)名為 ShapeFactory 的工廠接口,并具有一個(gè)名為 createShape 的方法,該方法返回一個(gè) Shape 類型的對(duì)象。具體的實(shí)現(xiàn),比如 CircleFactory 和 RectangleFactory,然后將實(shí)現(xiàn) createShape 方法來(lái)返回 Circle 和 Recangle 類型的對(duì)象。
工廠模式的一個(gè)優(yōu)點(diǎn)是,您可以通過(guò)添加新的子類來(lái)引入新的類型,而不必破壞現(xiàn)有的代碼。
單例
Singleton 是一個(gè)只允許一個(gè)類有一個(gè)實(shí)例的創(chuàng)建型模式。要?jiǎng)?chuàng)建一個(gè)單例類,類的缺省構(gòu)造函數(shù)需要是私有的。這樣可以確保其他類不能調(diào)用單例類上的新方法。不要使用缺省構(gòu)造函數(shù),創(chuàng)建一個(gè)靜態(tài)創(chuàng)建方法。如果不存在對(duì)象,此方法將調(diào)用私有構(gòu)造函數(shù),否則將返回已存在的緩存對(duì)象。
單例類解決的問(wèn)題是,它確保一個(gè)類只有一個(gè)實(shí)例,并且可以為該實(shí)例提供一個(gè)全局訪問(wèn)點(diǎn)。單例類對(duì)于緩存、日志記錄和注冊(cè)表等類很有幫助。
建造者
Builder 是一個(gè)可以讓你一步一步創(chuàng)建復(fù)雜對(duì)象的創(chuàng)建型模式。這允許使用相同的構(gòu)造代碼來(lái)實(shí)現(xiàn)不同的類型和表示。
如果存在一個(gè)可以有很多變體的類,那么構(gòu)造函數(shù)就會(huì)變得非常龐大和混亂。例如,想象一下有很多額外設(shè)備(防抱死制動(dòng)系統(tǒng),加熱座椅,后視攝像頭等)的“汽車”類。與其擁有一個(gè)包含所有選項(xiàng)的大型汽車構(gòu)造函數(shù),不如使用構(gòu)造函數(shù)類。構(gòu)建器類可以有一系列構(gòu)造汽車不同變體的方法。例如 buildFrame、 addWheels、 addBrakes、 addRearViewCamera 等等。.
構(gòu)建器模式的優(yōu)點(diǎn)是,在構(gòu)建不同的對(duì)象時(shí),可以重用相同的構(gòu)建代碼,而且構(gòu)建代碼與產(chǎn)品的業(yè)務(wù)邏輯是隔離的。
適配器
適配器模式是允許具有不同接口的兩個(gè)類進(jìn)行通信的模式。適配器作為類之間的轉(zhuǎn)換器工作,這樣它們就可以一起工作。例如,如果一個(gè)類輸出 XML,而另一個(gè)類需要 JSON 輸入。然后需要一個(gè)適配器來(lái)將 XML 轉(zhuǎn)換為 JSON。
代理
代理是一種結(jié)構(gòu)模式,允許您通過(guò)創(chuàng)建替代品或占位符來(lái)控制對(duì)對(duì)象的訪問(wèn)。如果存在不總是運(yùn)行的服務(wù)或資源,代理可以處理服務(wù)的初始化。這樣就不需要在所有使用服務(wù)的地方復(fù)制初始化代碼。
代理模式建議您創(chuàng)建一個(gè)具有與原始對(duì)象相同接口的新代理類。然后您可以在程序中使用代理對(duì)象而不是原始對(duì)象。然后,代理將工作委托給原始對(duì)象。
使用代理的好處是,您可以控制對(duì)原始對(duì)象的訪問(wèn),而且即使原始對(duì)象已關(guān)閉,代理也可以工作。
狀態(tài)
狀態(tài)模式在內(nèi)部狀態(tài)更改時(shí)處理對(duì)象的行為。例如,當(dāng)對(duì)象處于特定狀態(tài)時(shí),某些行為是不允許的。
狀態(tài)模式與有限狀態(tài)機(jī)緊密相連。這告訴我們一個(gè)程序只能處于一定數(shù)量的狀態(tài)。各個(gè)狀態(tài)的行為不同,并非所有的狀態(tài)都可以相互轉(zhuǎn)換。
為了創(chuàng)建封裝狀態(tài)之間轉(zhuǎn)換規(guī)則和狀態(tài)行為的邏輯,條件語(yǔ)句(if、 switch 或者模式匹配)是常見(jiàn)的。如果有很多狀態(tài),這個(gè)邏輯就會(huì)變得很大,很難維護(hù)。
狀態(tài)模式通過(guò)為每個(gè)狀態(tài)實(shí)現(xiàn)類來(lái)解決這個(gè)問(wèn)題。每個(gè)狀態(tài)類處理自己的行為和轉(zhuǎn)換到新?tīng)顟B(tài)的邏輯。原始對(duì)象(也稱為上下文)通過(guò)用新的狀態(tài)對(duì)象替換活動(dòng)狀態(tài)對(duì)象來(lái)更改狀態(tài)。所有狀態(tài)對(duì)象都需要遵循一個(gè)公共接口。
策略
策略模式允許在一個(gè)抽象下對(duì)一系列算法進(jìn)行分組。這允許運(yùn)行庫(kù)在算法之間切換。
策略模式與狀態(tài)模式非常相似。它不處理不同的狀態(tài),而是處理不同的算法或策略。
例如,谷歌地圖提供了使用汽車、步行、公共交通等方式進(jìn)行導(dǎo)航的選項(xiàng)。.這些選項(xiàng)使用不同的算法,但都可以在同一個(gè)客戶機(jī)中使用。
策略模式為不同的策略使用通用接口。原來(lái)的類變得獨(dú)立于具體的策略。原始類有一個(gè)用于存儲(chǔ)策略對(duì)象的字段。特定的策略對(duì)象負(fù)責(zé)執(zhí)行算法。客戶端負(fù)責(zé)選擇正確的算法。
使用策略模式的一個(gè)優(yōu)點(diǎn)是,您可以在將來(lái)添加額外的算法,而不會(huì)使原始類變得混亂。
觀察者
觀察者是一種描述訂閱機(jī)制的模式,它允許多個(gè)對(duì)象在它們觀察到的對(duì)象發(fā)生更改時(shí)得到通知。
所觀察到的對(duì)象通常稱為主題或發(fā)布者。更改發(fā)生時(shí)通知的對(duì)象稱為訂閱方。YouTube 就是這種觀察者模式的一個(gè)例子,每當(dāng)一個(gè)頻道發(fā)布一個(gè)新視頻,就會(huì)通知關(guān)注者。
發(fā)布者類應(yīng)該具有添加和刪除訂閱者以及通知所有訂閱者的方法。所有訂閱者都應(yīng)該具有相同的接口和方法,發(fā)布者可以調(diào)用這些接口和方法來(lái)通知他們更改。通常,發(fā)布者有一個(gè)訂閱者列表,循環(huán)訪問(wèn)訂閱者,并調(diào)用訂閱者“ update”方法來(lái)通知他們發(fā)布者的更改。