前言
一直想寫設(shè)計模式系列的博客,但是一直下不了決心去寫。一方面是自己剛開始工作,有時候騰不出那么多時間學習,另一方面是因為看了網(wǎng)上好多設(shè)計模式的文章,感覺他們總結(jié)的都很到位,自己再寫也寫不太好。但最后還是決定寫一下,因為知識只有自己梳理一遍才記得牢固,不管寫的好不好都是自己的。
這個系列我打算以初學者的身份一點一點去挖掘每一個設(shè)計模式,用宇明大佬教的《費曼學習法》用講解的語氣去寫每一篇文章。ok,言歸正傳,我們開始今天的文章——設(shè)計模式(一)設(shè)計模式概述
在看到標題的時候,我想作為一個初學者應(yīng)該會先提出這些問題:
- 什么是模式?什么是設(shè)計模式?
- 我們?yōu)槭裁匆獙W習設(shè)計模式?設(shè)計模式對我們開發(fā)有什么幫助?
- 我們?nèi)绾螌W習設(shè)計模式?
接下來我們就帶著這些問題來學習今天的內(nèi)容。
一、什么是模式?什么又是設(shè)計模式?
什么是模式?我們先從字面意思來理解,“?!蹦P汀⒛>?,我們可以看做是一種標準,“式”形式、方式,我們可以看做是一種方法,兩者組合在一起就是“標準化的方法”叫做模式。
舉個很恰當了例子:中國的四大發(fā)明之一,活字印刷術(shù)的誕生過程就是一種模式的產(chǎn)生。在沒有活字印刷術(shù)之前,每頁文字刻成一個板子,如果一個字錯了就得重新雕刻,錯誤率很高,成本也高,效率還低。之后演變成為每個字為單獨小板,印刷文章的時候只需要在大板子上根據(jù)需求排列不同的字就可以了,這些字不僅雕刻起來錯誤率低,還可以重復(fù)不同的文章使用。這是一種標準化方法的演變過程,也是一種模式的誕生。
每個模式都描述了一個在我們的環(huán)境中不斷出現(xiàn)的問題,然后描述了該問題的解決方案的核心,通過這種方式,我們可以無數(shù)次地重用那些已有的成功的解決方案,無須再重復(fù)相同的工作。簡而言之就是:模式是在特定環(huán)境下人們解決某類重復(fù)出現(xiàn)問題的一套成功或有效的解決方案。
上面我們了解了模式,但有的朋友該說了,我們是軟件開發(fā)工作者,知道模式有什么用呢?別著急,下面我們就來認識一下軟件模式。
軟件模式,如果按剛才我們理解的“模式”,軟件模式就可以解讀為:軟件生命周期內(nèi)的一些標準化方法。我們知道軟件的生命周期并不單單只開發(fā)周期,軟件前期的需求分析,后期的迭代維護都屬于軟件的生命周期,所以相對應(yīng)的在每個階段都會有對應(yīng)的模式。作為開發(fā)者我們接觸最多的就是開發(fā)階段,而在開發(fā)階段使用最多的應(yīng)該就是設(shè)計模式了。那什么又是設(shè)計模式呢?
據(jù)網(wǎng)上搜索得知:設(shè)計模式(Design Pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計經(jīng)驗的總結(jié),使用設(shè)計模式是為了可重用代碼、讓代碼更容易被他人理解并且保證代碼可靠性。其實說白了,設(shè)計模式就是經(jīng)過無數(shù)填坑人的努力所總結(jié)的一套標準化的被所有開發(fā)者承認的代碼設(shè)計方案。
設(shè)計模式一般包含模式名稱、問題、目的、解決方案、效果等組成要素,其中關(guān)鍵要素是模式名稱、問題、解決方案和效果。
模式名稱(Pattern Name)通過一兩個詞來描述模式的問題、解決方案和效果,以便更好地理解模式并方便開發(fā)人員之間的交流,絕大多數(shù)模式都是根據(jù)其功能或模式結(jié)構(gòu)來命名的;
問題(Problem)描述了應(yīng)該在何時使用模式,它包含了設(shè)計中存在的問題以及問題存在的原因;
解決方案(Solution)描述了一個設(shè)計模式的組成成分,以及這些組成成分之間的相互關(guān)系,各自的職責和協(xié)作方式,通常解決方案通過UML類圖和核心代碼來進行描述;
效果(Consequences)描述了模式的優(yōu)缺點以及在使用模式時應(yīng)權(quán)衡的問題。
個人感覺這些已經(jīng)很全面的解釋了什么是設(shè)計模式,之后我也打算從這四個方面去分析每一種模式。
二、設(shè)計模式是為了解決什么樣的問題?我們?yōu)槭裁匆獙W習設(shè)計模式?
認識完設(shè)計模式我們肯定會產(chǎn)生以下疑問?我們?yōu)槭裁匆獙W習設(shè)計模式?它在我們開發(fā)當中都解決了哪些問題?
通過學習我覺得學習設(shè)計模式可以解決以下三個問題:
1、避免重復(fù)造輪子
學習計算機我們肯定都聽過這句話“不要重復(fù)造輪子”,設(shè)計模式首先解決的就是我們重復(fù)造輪子的問題。
舉個栗子:在沒有學習設(shè)計模式的時候,我們使用圖片加載或者其他工具類,肯定是經(jīng)過大量的編程,走過很多彎路,填過很多坑才會想到“我們應(yīng)該封裝一下,單獨一個實例這樣更加便于管理”,于是我們開始封裝,廢了好大勁封裝成功,之后學習完 “單例模式”發(fā)現(xiàn),咦,這不就是我封裝的那個方式么?如果早學了設(shè)計模式,我就。。。。所以,在時間就是金錢的今天,設(shè)計模式無疑會為有助于我們提高開發(fā)和設(shè)計效率,但它不保證一定會提高。
2、降低溝通成本
工作中我們不可能是一直獨立開發(fā),肯定會跟別人協(xié)調(diào)開發(fā)。只要有合作就少不了溝通,設(shè)計模式也能解決開發(fā)人員之間的溝通問題。
再舉個栗子:你從零開發(fā)了一個項目,后來項目越做越大,功能模塊也越來越多,多到你天天加班也弄不完的情況,這個時候你向老板提出“漲工資不然不干了,然后老板開始給你各種畫餅。。?!保ǔ哆h了),這時候你向老板提出需要一個幫手,然后老板給你招來一個小弟,你需要帶他熟悉項目,你對他說我這個地方用了“單例模式”,這里用了“裝飾者模式”,然后這里是“工廠模式”,然后小弟懵逼了。然后你還得費好大勁去講解你是怎么實現(xiàn)的這些模式。。。很顯然小弟并不了解設(shè)計模式,不然你就可以省下很多時間多寫幾個bug了。
因為設(shè)計模式提供了一套通用的設(shè)計詞匯和一種通用的形式來方便開發(fā)人員之間溝通和交流,使得設(shè)計方案更加通俗易懂,所以無論你使用哪種編程語言,做什么類型的項目,甚至你處于一個國際化的開發(fā)團隊,當面對同一個設(shè)計模式時,你和別人的理解并無二異,因為設(shè)計模式是跨語言、跨平臺、跨應(yīng)用、跨國界的。
3、優(yōu)秀的復(fù)用性和可擴展性
上大學的時候我們學過,一個優(yōu)秀的軟件需要有六大特性:功能性、可靠性、可用性、效率、可維護性、可移植性。然而很多開發(fā)人員在開發(fā)的時候多半不會考慮這些東西。因為國內(nèi)的開發(fā)環(huán)境大多是先出結(jié)果,出問題了再說。
所以,如何在有限的時間內(nèi)開發(fā)出優(yōu)秀的軟件是成為優(yōu)秀開發(fā)人員的必修之路。大部分設(shè)計模式都兼顧了系統(tǒng)的可重用性和可擴展性。例如:代碼中經(jīng)常使用某個功能,我們可以使用“單例模式”把他封裝起來,如果考慮某個地方的可擴展性,我們可以使用“裝飾模式”等等。
三、常用的設(shè)計模式都有哪些?
經(jīng)過無數(shù)前輩的總結(jié),常用的設(shè)計模式主要有23種,而這23種設(shè)計模式又可以分為三大類:創(chuàng)建型模式(5種)、結(jié)構(gòu)型模式(7種)和行為型模式(11種)。
其中創(chuàng)建型模式主要用于描述如何創(chuàng)建對象,結(jié)構(gòu)型模式主要用于描述如何實現(xiàn)類或?qū)ο蟮慕M合,行為型模式主要用于描述類或?qū)ο笤鯓咏换ヒ约霸鯓臃峙渎氊煛?/strong>下圖是23種模式的具體分類:
| 創(chuàng)建型模式 Creational Pattern |
|---|
| 單例模式 Singleton |
| 原型模式 Prototype Pattern |
| 簡單工廠模式 Simple Factory Pattern |
| 工廠方法模式 Factory Method Pattern |
| 抽象工廠模式 Abstract Factory Pattern |
| 建造者模式 Builder Pattern |
| 結(jié)構(gòu)型模式 Structural Pattern |
|---|
| 適配器模式 Adapter Pattern |
| 橋接模式 Bridge Pattern |
| 組合模式 Composite Pattern |
| 裝飾模式 Decorator Pattern |
| 外觀模式 Fa?ade Pattern |
| 享元模式 Flyweight Pattern |
| 代理模式 Proxy Pattern |
| 行為型模式 Behavioral Pattern |
|---|
| 職責鏈模式 Chain of Responsibility Pattern |
| 命令模式 Command Pattern |
| 解釋器模式 Interpreter Pattern |
| 迭代器模式 Iterator Pattern |
| 中介者模式 Mediator Pattern |
| 備忘錄模式 Memento Pattern |
| 觀察者模式 Observer Pattern |
| 狀態(tài)模式 State Pattern |
| 策略模式 Strategy Pattern |
| 模板方法模式 Template Method Pattern |
| 訪問者模式 Visitor |
注:之后每學習一個模式,我們會在表格后面增加模式的概述,使用場景等內(nèi)容
四、我們?nèi)绾螌W習設(shè)計模式?
我從大學開始接觸設(shè)計模式,雖然是門選修課,但它是我唯一 一門沒有逃過一節(jié)課的選修課。畢業(yè)后我也從事了近兩年的開發(fā)工作。在這期間我體會到了設(shè)計模式的種種便利,也了解一些朋友對設(shè)計模式的看法。在這里我想分享一下自己學習設(shè)計模式的心得體會,供大家參考:
1、不要畏懼。工作期間我跟很多同事談?wù)撨^設(shè)計模式,他們大多數(shù)的反應(yīng)是“那個感覺挺難的,現(xiàn)在沒打算去學。”很多人還沒開始就已經(jīng)退縮了。其實掌握設(shè)計模式并不是很難的事情,我們只需要拆分他們,一個一個模式去熟悉,一個例子一個例子去看、去模仿,多思考,多實踐,一定可以掌握。關(guān)鍵是要開始去學。
2、抓住重點。其實學習每一個設(shè)計模式只需要抓住以下幾點,我們就能大概掌握這種模式。
- 這個設(shè)計模式是要解決什么問題,需要在那種情況下使用?
- 這個設(shè)計模式的結(jié)構(gòu)圖是什么樣的?
- 這個設(shè)計模式的優(yōu)缺點分別是什么?
- 在現(xiàn)實和代碼中分別能舉出什么樣的使用該模式的例子?
3、親身實踐。老話說:“紙上得來終覺淺,絕知此事要躬行”,看十遍例子也不如敲一遍代碼,一定要把例子敲一遍,并且舉一反三自己設(shè)計例子。這樣才能記得牢固。
4、不能濫用。千萬不要濫用模式,不要剛學了一兩個模式就想在代碼中硬套。每個模式都有自己的適用場景,不能為了使用模式而使用模式。要做到具體情況具體分析,濫用設(shè)計模式很可能寫出一堆垃圾代碼。
5、活學活用。我這里直接用劉偉老師的總結(jié)來解釋。
設(shè)計模式的“上乘”境界:“手中無模式,心中有模式”。模式使用的最高境界是你已經(jīng)不知道具體某個設(shè)計模式的定義和結(jié)構(gòu)了,但你會靈活自如地選擇一種設(shè)計方案【其實就是某個設(shè)計模式】來解決某個問題,設(shè)計模式已經(jīng)成為你開發(fā)技能的一部分,能夠手到擒來,“內(nèi)功”與“招式”已渾然一體,要達到這個境界并不是看完某本書或者開發(fā)一兩個項目就能夠?qū)崿F(xiàn)的,它需要不斷沉淀與積累,所以,對模式的學習不要急于求成,要循序漸進。
設(shè)計模式目錄
設(shè)計模式(一)—— 認識設(shè)計模式
設(shè)計模式(二)—— 技術(shù)直男正確“面向?qū)ο蟆钡牧笤瓌t
設(shè)計模式(三)—— 單例模式
設(shè)計模式(四)—— 原型模式
設(shè)計模式(五)—— 簡單工廠模式
五、結(jié)語
最后用軟件工程大師之一John Vlissides的著作《設(shè)計模式沉思錄》(Pattern Hatching Design Patterns Applied)中的一句話來結(jié)束這篇文章:
模式從不保證任何東西,它不能保證你一定能夠做出可復(fù)用的軟件,提高你的生產(chǎn)率,更不能保證世界和平。模式并不能替代人來完成軟件系統(tǒng)的創(chuàng)造,它們只不過會給那些缺乏經(jīng)驗但卻具備才能和創(chuàng)造力的人帶來希望。
本文參考:
《設(shè)計模式——可復(fù)用面向?qū)ο筌浖幕A(chǔ)》
《Head First設(shè)計模式》
《大話設(shè)計模式》
【劉偉 http://blog.csdn.net/lovelion】