2.5 用上設(shè)計模式你就厲害了?

為什么用了設(shè)計模式后反而沒有那么厲害?
1. 為了用而用
首先想要使用上某個設(shè)計模式,然后就修改代碼讓其使用上。比方說為了將采用策略模式,而修改代碼使其可以使用上策略模式,這就是為了用上設(shè)計模式而用上設(shè)計模式。
假設(shè)我們有一個動物園,目前里面只有獅子和老虎,我們需要讓它們發(fā)出叫聲。
如果我們采取直觀的方法,我們可以創(chuàng)建一個 Animal 類,并為每種動物定義一個子類:
這樣,我們可以讓每個動物發(fā)出叫聲:
但是,如果我們強制使用策略模式,我們需要首先定義一個策略接口,然后為每種動物的叫聲創(chuàng)建一個策略:
然后,我們可以像這樣使用它:
雖然策略模式提供了一種更靈活的方式來管理動物的叫聲,但在這種情況下,它卻引入了不必要的復(fù)雜性。在這個簡單的例子中,使用策略模式并沒有帶來實際的好處,反而使代碼變得更難理解。這就是“為了使用設(shè)計模式而使用設(shè)計模式”的問題所在。
2. 過度設(shè)計
有時候,為了提高擴展性,可能會過度使用設(shè)計模式,造成“過度設(shè)計”。這可能會使代碼變得冗余和復(fù)雜,反而降低了代碼的可讀性和可維護性。
例如說用戶的點擊操作記錄統(tǒng)計功能,為了未來可能的擴展性,你可能考慮使用觀察者模式,讓其他對象可以在用戶點擊時接收到通知。
然后在主程序中,你可能這樣使用:
雖然這個設(shè)計可以讓你在未來很容易地添加更多的觀察者,但是如果你從來不需要添加其他觀察者,那么這個設(shè)計就顯得過度了。其實,一個簡單的整數(shù)變量就可以滿足你記錄點擊次數(shù)的需求,無需引入觀察者模式的復(fù)雜性。
3.?預(yù)先優(yōu)化
經(jīng)常為了未來的需求做考慮,然后基于未來的需求做抽象設(shè)計,然后引入了設(shè)計模式。必然說,需要實現(xiàn)一個加法運算,那你直接寫一個加法函數(shù)即可,不需要為了這一個功能點直接開發(fā)一個計算器。
但是,如果過度設(shè)計,你可能會采用策略模式,來設(shè)計一個更抽象的計算器:
雖然這個設(shè)計看起來非常靈活,你可以通過修改 Calculator 的 Operation 來改變其行為,但是如果你只需要執(zhí)行加法運算,這個設(shè)計顯然過于復(fù)雜。過度設(shè)計往往會使代碼變得更難理解和維護,所以在做設(shè)計決策時,我們需要找到復(fù)雜性和靈活性之間的平衡。
關(guān)于使用設(shè)計模式的建議
清晰的項目結(jié)構(gòu): 在考慮引入設(shè)計模式前,確保你的項目業(yè)務(wù)模型和結(jié)構(gòu)是清晰的。如果你的代碼是基于面向過程,缺乏適當(dāng)?shù)姆庋b和抽象,那么引入設(shè)計模式可能會使代碼更加復(fù)雜,反而不利于維護。
目標(biāo)是為了可維護與可拓展: 設(shè)計模式應(yīng)當(dāng)被用來提高代碼的可維護性和可擴展性。如果引入設(shè)計模式并未達到這樣的效果,那么可能需要重新考慮你的設(shè)計。
避免過度設(shè)計和預(yù)先優(yōu)化: 你應(yīng)該試圖滿足當(dāng)前的需求,而不是過度設(shè)計以滿足可能的未來需求。過度追求設(shè)計模式可能導(dǎo)致過度設(shè)計,這可能會使代碼變得不必要的復(fù)雜和難以理解。
理解設(shè)計模式的意圖和原理,使用設(shè)計模式之前,確保你理解其意圖和原理,而不僅僅是如何實現(xiàn)它。設(shè)計模式并不是代碼模板,而是用來解決特定設(shè)計問題的通用解決方案。理解設(shè)計模式的背后原理,可以幫助你判斷何時應(yīng)該使用它,以及如何根據(jù)具體情況調(diào)整它。
設(shè)計模式應(yīng)用需要適度: 設(shè)計模式的應(yīng)用是為了解決實際問題,而不是為了讓代碼看起來“專業(yè)”或“復(fù)雜”。如果在不需要的情況下使用設(shè)計模式,或者過度使用設(shè)計模式,可能會使代碼變得不必要的復(fù)雜和難以理解。
考慮團隊因素: 如果你的團隊成員對某種設(shè)計模式不熟悉,那么在項目中引入這種設(shè)計模式可能會帶來問題。在決定使用哪種設(shè)計模式時,你需要考慮到團隊成員的知識和技能。
重構(gòu)是持續(xù)的過程: 在軟件開發(fā)過程中,隨著需求的變化和項目的發(fā)展,可能需要對代碼進行重構(gòu)。在這個過程中,可能會發(fā)現(xiàn)一些設(shè)計模式的應(yīng)用場景。因此,不需要一開始就強求使用設(shè)計模式,而是在重構(gòu)過程中逐步引入。
設(shè)計模式介紹
設(shè)計模式通常被歸類為創(chuàng)建型、結(jié)構(gòu)型和行為型三大類,各有不同的目標(biāo)和應(yīng)用場景。
以下是對這23種設(shè)計模式的歸類和簡單總結(jié):
創(chuàng)建型模式
這類模式的主要關(guān)注點是如何創(chuàng)建對象,特別是在系統(tǒng)要求對創(chuàng)建過程進行更多控制和管理時。
單例模式:確保一個類只有一個實例,并提供全局訪問點。
原型模式:使用復(fù)制現(xiàn)有對象的方式來創(chuàng)建新對象。
建造者模式:分離對象的構(gòu)建和表示,同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
工廠方法模式:定義一個創(chuàng)建對象的接口,但讓子類決定要實例化哪個類。
抽象工廠模式:提供一個接口以創(chuàng)建一系列相關(guān)或依賴對象,而無需指定具體的類。
結(jié)構(gòu)型模式
這類模式關(guān)注如何組織不同的對象和類以形成更大的結(jié)構(gòu),同時保持結(jié)構(gòu)的靈活和高效。
適配器模式:使接口不兼容的類可以一起工作,將一個類的接口轉(zhuǎn)換為客戶希望的另一個接口。
橋接模式:將抽象和實現(xiàn)解耦,以便兩者可以獨立變化。
組合模式:允許將對象組合成樹形結(jié)構(gòu)以表示"部分-整體"的層次結(jié)構(gòu),使得用戶對單個對象和組合對象的使用具有一致性。
裝飾模式:動態(tài)地給一個對象添加一些額外的職責(zé),就增加功能來說,裝飾模式比生成子類更為靈活。
外觀模式:為一組接口提供一個統(tǒng)一的高層接口,使得使用更為方便。
享元模式:運用共享技術(shù)來有效地支持大量細粒度的對象。
代理模式:為其他對象提供一種代理以控制對這個對象的訪問。
行為型模式
這類模式關(guān)注對象之間的通信,它們主要解決的是"對象如何、何時、以何種方式進行交互"的問題。
模板方法模式:定義算法的框架,而將一些步驟的實現(xiàn)延遲到子類。
訪問者模式:為一個對象結(jié)構(gòu)中的元素提供新的操作而不改變其類的結(jié)構(gòu)。
迭代器模式:提供一種方法順序訪問一個聚合對象中各個元素,而又不暴露該對象的內(nèi)部表示。
觀察者模式:定義對象間的一種一對多的依賴關(guān)系,使得每當(dāng)一個對象改變狀態(tài),則所有依賴于它的對象都會得到通知并被自動更新。
中介者模式:用一個中介對象來封裝一系列的對象交互,中介者使各對象不需要顯式地相互引用,從而使其耦合松散,而且可以獨立地改變它們之間的交互。
命令模式:將一個請求封裝為一個對象,從而使用戶可以使用不同的請求對客戶進行參數(shù)化;對請求排隊或記錄請求日志,以及支持可撤銷的操作。
狀態(tài)模式:允許一個對象在其內(nèi)部狀態(tài)改變時改變它的行為,對象看起來似乎修改了它的類。
策略模式:定義一系列的算法,把它們一個個封裝起來,并且使它們可以互相替換。
責(zé)任鏈模式:使多個對象都有機會處理請求,從而避免請求的發(fā)送者和接收者之間的耦合關(guān)系。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有對象處理它為止。
備忘錄模式:在不破壞封裝性的前提下,捕獲一個對象的內(nèi)部狀態(tài),并在該對象之外保存這個狀態(tài),以便以后恢復(fù)對象到這個狀態(tài)。
解釋器模式:給定一個語言,定義它的語法的一種表示,并定義一個解釋器,這個解釋器使用該表示來解釋語言中的句子。