寫在前面:
學習過程中不僅要熟練掌握技能,理論的消化吸收也必不可少。雖然個人更傾向於學習技術類的東西(短時間的精力投入很快就能看到成效...),但看了很多前輩的經驗總結後才知道理論性的東西是絕對不能忽視的,畢竟理論對實踐有著重要的指導意義。而了解“設計”相關的東西,會對“實現”產生潛移默化的影響,雖然不能在短時間內看到讓人欣喜的變化,但可能有一天回過頭來一想“哦~,原來我這個不錯的小習慣是當年在那本書上學到的啊”
一。什麼是設計模式?
繞了一圈之後讓我們又回到這個話題吧(看書之前問自己一遍,看完之後再問自己一遍,答案之間的差異就是感悟了)
之前:
自問:設計模式是什麼?
自答:是一些系統設計的指導原則吧,不過我現在天天寫程式碼,應該也用不到設計層面上的東西。
自問:哦,那具體是什麼?
自答:不清楚,不過我見過一些前輩的程式碼,結構很複雜,一看就很上檔次的那種,那些應該就用了設計模式吧,所以程式碼有沒有應用設計模式應該就是高手與新手的區別了。等我成了高手之後,這種東西還不信手拈來,嗯,不說了,我寫程式碼去了,好好累積專案經驗。
之後:
自問:設計模式是什麼?
自答:設計模式是由程式碼結構優化經驗萃取出來的理論知識,應用成熟的設計模式能夠增強程式碼的可複用性、可擴充性與可維護性。
自問:你好像很專業的樣子,那好,既然設計模式有這麼多好處,那是不是應用了設計模式的設計都是好設計?
自答:當然不是,我們不能為了使用模式而使用模式。設計模式可不能濫用,畢竟應用設計模式必須要作出一些犧牲(比如增加類別結構的複雜性...),所以濫用設計模式的話是會出事的。而且,就算我們有了錘子,也不能把所有問題都看作釘子吧?
P.S.還記得學習正規表示式的總結:能不用就儘量不要用(最大限度的避免濫用),設計模式與之類似,不能看���什麼問題都往模式上靠,只有當我們非常確定在當前情景下確實需要用設計模式來優化我們的設計時,才考慮使用設計模式(至於到底用不用,還要權衡重構的成本與優化的收益...)
二。要不要使用設計模式?
這是個值得思考的問題,畢竟現在我們已經擁有了一把錘子,要不要用它當然成了問題,畢竟不是所有的問題都可以用錘子來解決。退一步講,即便所有問題都能用錘子解決,我們也不確定使用錘子是不是最好的解決方案(拔釘子的話,可能用鉗子更好些...)
當我們拿著某個設計模式想放進我們的程式碼中時,最好權衡一下利弊,誠然,設計模式具有的設計上的彈性一定會給我們之後的維護變更帶來些便利。但是利與弊到底哪個更多一些,我們需要先回答幾個問題再做決定:
- 我們的專案是不是幾乎不涉及維護或者沒有後續版本,那麼我們引入設計模式還有必要嗎?
- 我們專案的規模是不是大到了不用設計模式不行的地步?
- 這個設計模式用在這裡合適嗎?有沒有更合適的?
- 非要用設計模式嗎?可不可以用幾個簡單的設計原則來代替?
- 引入設計模式之後,程式碼結構的複雜度大大增加,重構的成本我們可以接受嗎?
如果深思熟慮之後,還是覺得使用設計模式比較好,那麼,放心去用吧,之後好好享受設計模式帶來的好處吧
三。設計原則總結
設計原則都是一些簡單的指導意見,沒有固定的實現,因而設計原則也更加靈活,常見的設計原則如下:
- 封裝變化(把易於發生變化的部分抽出來,以減少其變化對其它部分的影響)
- 多用組合,少用繼承(組合比繼承更有彈性)
- 針對介面程式設計,不針對實現程式設計(使用介面可以避免直接依賴具體類)
- 為互動物件之間的鬆耦合設計而努力(更鬆的耦合意味著更多的彈性)
- 類應該對擴充開放,對修改關閉(open-close 原則)
- 依賴抽象,不要依賴具體類(減少對具體類的直接依賴)
- 只和朋友交談(密友原則)
- 別找我,我會找你(Don't call me, I will call you back.安卓開發的大原則)
- 類應該只有一個改變的理由(單一責任原則)
能用設計原則解決的問題就不要用設計模式(殺雞焉用宰牛刀...),因為設計原則實現起來更加靈活,更加輕巧(不用去考慮模式的條條框框...)
四。設計模式總結
| 名稱 | 特點 |
| 策略模式(Strategy) | 把可以替換的演算法步驟封裝成一個個演算法族,供執行時動態選擇 |
| 觀察者模式(Observer) | 定義並維護物件之間的一對多關係 |
| 裝飾者模式(Decorator) | 建立擁有共同超類的裝飾者與被裝飾者來實現功能的動態擴充 |
| 工廠模式(Factory) | 封裝物件的建立過程,包括工廠方法模式和抽象工廠模式 |
| 單件(例)模式(Singleton) | 用來建立唯一的物件(比如資料庫連線物件,執行緒池物件等等) |
| 命令模式(Command) | 封裝方法呼叫細節,解耦請求者與執行者 |
| 配接器模式(Adapter) | 用來實現不同介面間的轉換 |
| 外觀模式(Facade) | 為複雜的子系統提供簡單易用的高層介面 |
| 範本方法模式(Template Method) | 用來封裝演算法骨架(流程),某些步驟由子類實現 |
| 迭代器模式(Iterator) | 用來封裝遍歷細節 |
| 組合模式(Composite) | 提供一種層級結構,使得我們能夠忽略物件與物件集合間的差異,一視同仁地對待它們 |
| 狀態模式(State) | 把所有動作都封裝在狀態物件中,狀態持有者將行為委託給當前狀態物件 |
| 代理模式(Proxy) | 通過插入第三方(代理物件)來分離呼叫者和被呼叫者(不同於執行者) |
| 複合模式(Compound) | 將多個模式組合結合起來形成一個“框架”,以解決一般性問題 |
| 橋接模式(Bridge) | 將抽象的控制類與具體實現類通過組合解耦,使得抽象層類與實現層類可以對立與對方而變化 |
| 生成器模式(Builder) | 用來封裝組合結構(樹形結構)的構造過程,與迭代器模式類似,都隱藏了組合結構的內部實現,只提供一組用於建立組合結構的介面 |
| 責任鏈模式(Chain of Responsibility) | 讓一個請求可以被一組接收者順序處理,類似於 Android 處理請求的方式:一個接收者捕獲請求後可以 return true 消費掉請求,也可以 return false 傳遞給接收者佇列中的下一個接收者(觀察者) |
| 蠅量模式(Flyweight) | 抽象出物件管理層來統一管理大量的同類型物件,以減少執行時物件例項的個數,減少記憶體消耗 |
| 解釋器模式(Interpreter) | 用來為簡單語言建立解釋器,將語法規則直接映射為各個類,結構簡單,但效率較低 |
| 中介者模式(Mediator) | 引入中介者來封裝多個物件間的複雜互動,以降低同級(在類結構統一層次上的)物件間的依賴 |
| 備忘錄模式(Memento) | 支援物件狀態的儲存與恢復,並將物件狀態資料封裝起來,獨立於客戶程式碼以提供保護(Java 中可以結合序列化反序列化技術來實現該模式) |
| 原型模式(Prototype) | 以現有的物件為原型,通過 clone 得到新的物件(以簡化新物件的建立過程) |
| 訪問者模式(Visitor) | 為組合結構新增新的操作,而不需要頻繁的改變組合結構 |
五。面向物件的設計(Object Oriented Design)
一直伴隨著 OOD 的問題就是“折衷”(或者說是“取捨”),最簡單的例子——要不要用設計模式?
- 用,意味著將產生複雜的類別關係,多層的抽象,我們將犧牲易讀性換取易擴充性、易維護性或者其它特性
- 不用,意味著我們不需要對現有程式碼進行重構(或者不用去在複雜的設計上耗費過多的時間),但使用設計模式的所有好處我們就都享受不到了
二者選其一,這就是一個“取捨”,或者創造第三個選項(比如使用設計原則),這就是一個“折衷”
寫在後面:關於《Head First 設計模式》
很少寫書評,因為每個人的喜好不同,不好作推薦(甚至有時候喜歡一本書僅僅是因為喜歡作者的行文風格而已,從而不自覺的認為書籍內容不錯。。)
這本書是前輩推薦的,看完之後覺得大部分章節講的很不錯,既細緻又通俗,但感覺某些章節並不是很好(比如第一章策略模式的例子不很貼切,和後面的遠端代理部分細節展開的不合理)
總體來說,作為入門書籍的話,《Head First 設計模式》還是不錯的,個人感受,僅供參考
暫無評論,快來發表你的看法吧