- 首先介紹方法論,參考了《大道至簡 — 軟件工程實踐者的思想》
- DP與Spring、SOA類比,皆出于實踐
- DP的必要性和要點,輔助代碼簡要說明
- 拋磚引玉,介紹幾個DP:
- Factory Pattern
- Decorator Pattern
- Proxy Pattern
- SingLeton Pattern
- Command Pattern
- 其它
- 介紹點:
- a) 使用一些可與現實結合的生動例子(引用網上資源)
- 介紹其本質(個人理解)
- 簡要介紹其如何使用
<一>開幕
大家好,我是crazycy,今天我們討論的主題是Design Pattern
首先感謝千年一嘆的安排和付出,雖然他極其的忙。
今天的話題可能不很適合初學者,對于初學者的建議可以看我的文章:http://www.tkk7.com/crazycy/archive/2006/07/07/57106.html
<二> 設計模式的起因
在談設計模式之前,我們想一下:為什么會有設計模式?
Christopher Alexander說:每一個模式描述了一個在我們周圍不斷重復發生的問題以及該問題的解決方案的核心。
咱們大多是做研發的,往往有自己的體會,遇到問題--解決問題,這個過程中會發現有一些問題及其解決方案不斷變換面孔重復出現,其后面的有著共同的本質。實際上這些本質就是模式。
從哲學角度說,設計模式的出現是實踐經驗的結晶,是產生于實踐并指導實踐。
<三>聯想
說到這里,我們現在用的、談的比較火爆的就是Spring Hibernate之類的框架。是吧?
Struts直接革新了Web Model 2的應用。
Hibernate直接解決了持久層的非面向對象的尷尬。
Spring直接挑戰了原先的Java EE框架。
這些都是源于實踐。選擇一種架構、一種技術的依據是什么? Rod Johnson 認為,應該是基于實踐的依據、來自歷史項目或親自試驗的經驗,而不是任何形式的偶像崇拜或者門戶之見。 這個是循序方法:實踐的反復總結。(十足的哲學)
為什么說Spring是實踐的總結:大家可以看一下我的blog的一片文章http://www.tkk7.com/crazycy/archive/2006/06/05/50519.aspx 比較簡略。
<四> 哲學
周愛民先生的《大道至簡 — 軟件工程實踐者的思想》對方法、方法論有如下描述:
============================================================================================================
3. 方法
推動這種邏輯向前發展的,是 “ 方法 ” 和 “ 方法論 ” 的出現。長期的編程實踐,自然的歸演與總結,必須沉淀為某種 ( 軟件開發 ) 方法,于是 “ 過程 ” 出現了,于是 “ 對象 ” 出現了,于是相關的方法論也就出現了。
這是實踐的成果。方法不是某個人或者某個組織創造的。瓜熟而蒂落,實踐積累達到一定的程度,微軟不提出某個方法, IBM 也會提出這個方法。即便他們都不提出,可能你自己已經在使用這個方法了。
方法并不神秘,因為它就是你今天正在做的、從事的和實現的。正如 “ 模式 ” 是一種方法,而模式就是你昨天書寫代碼的那個行為。只不過, GoF 歸納、抽取、提升了這些行為的內在規律。
你看不到你做事的行為,也就不能理解 “ 模式 ” 作為一種方法的價值。所以大師們眾口一詞:模式需要一定的編程經驗才能理解。
同理,理解過程也需要編程經驗,理解對象也需要編程經驗,理解 MDA 與 SOA 還是需要編程經驗。
—— 這可能就發生在你去回顧你上一行代碼編寫的經過,或者上一個項目失敗的經歷的那一瞬息。經驗來源于回顧、理解與分析,而不是你將要寫的下一行代碼。
有人在寺院掃了一輩子的落葉而得道,也有人因為一句話而得道。
感覺不過癮可以看一下我的blog文章:
http://www.tkk7.com/crazycy/archive/2006/05/24/47799.html
而對于方法論,查了一下大概闡述如下:方法論是一套完整的實踐引導體系,是指導實踐的理論基礎,是人們在長期社會實踐中總結和摸索出來的,符合客觀發展規律的,符合人們對研究對象進行科學分析與判斷的社會實踐進程或步驟。方法是實踐的成果,如同瓜熟蒂落,實踐積累達到一定程度,必然會提出方法。
<五>DP產生的必要性和目標
咱們大家對OO編程都熟悉,OO的三個基本特征:封裝、繼承、多態。
OO解決不了的問題--Java為例子:
java語言要求將一個類實例化時,必須調用這個類的具體類的構造子,所以java語言給出的類的實例化方法無法做到只依賴抽象類型。
這造成了調用者合被調用者的一種緊耦合
設計模式追求的目標是調用者和被調用者之間的解耦。
示例:
消費一個對象的客戶端只依賴于對象的抽象類型,而不是具體類型
A類:
State state = new StartState();
工廠類:
public class StateFactory {
public State static createState() {
State state = new. StartState();
return state;
}
}
A類:
State state = StateFactory.createState();
這樣就很容易理解工廠類就是生產對象,也就是創建對象,把對象的創建過程從類A中摘取出來.
這樣也就達到了DP的目標,也正是因為這個目標的提出,才誕生了IoC。
可以參考的我blog文章:http://www.tkk7.com/crazycy/archive/2006/03/19/36068.aspx
這里有朋友問抽象工廠和工廠方法兩個模式的區別,
可以參考我的blog文章:http://www.tkk7.com/crazycy/archive/2006/10/08/73858.html
<六>介紹幾個模式
Decorator模式是
1. 對真實對象進行包裝
2. 使其功能擴展
3. 表現形式:new 包裝類1(new 包裝類2(真實對象));這樣真實對象就具備了本身、包裝類1、包裝類2的功能;
4. 實現時只需要把真實對象做為包裝類的聚合對象;
實在不行就想想ML時,如果帶上TT后,原來的不影響,而且還安全了。主要就是包裝原先的對象。
可參考我的blog文章:http://www.tkk7.com/crazycy/archive/2006/04/30/44169.html
Dynamic Proxy模式是
代理模式(Proxy,這里側重于Dynamic Proxy)可以理解成給一個對象提供一個代理對象,這個代理對象就是把原對象進行包裝,使其與調用處理器相關聯。
因為代理對象和真實對象具有相同的接口,客戶訪問時,通過接口調用代理實例的方法,這個調用會被分發到該實例對應的處理器。處理器在把客戶端調用傳遞給真實的對象之前或者之后,可執行某個操作,也可以選擇不把這個調用傳遞給真實的對象。
1. 將真實對象包裝
2. 使其與調用處理類綁定
3. 表現形式:Proxy.newProxyInstance(realObject.getClass(). getClassLoader(), realObject.getClass().getInterfaces(), new InvocationHandler(realObj));這樣真實對象就與InvocationHandler類邦定了,對外是一個代理類的形式;
4. 實現時只需要把真實對象做為調用處理器的聚合對象
實在不行就想想:垂簾聽政:猶如清朝康熙年間的四大府臣,很多權利不在皇帝手里,必須通過輔佐大臣去辦;
具體示例參加blog:
http://www.tkk7.com/crazycy/archive/2006/04/29/44006.html
Command模式
本質:將調用操作的對象 和 知道如何實現改操作的對象 解耦。
1 調用者
發出請求的對象,請求被包裝成請求對象的形式(側重于對象)
2 接收者
知道如何處理某個請求的對象。
3 關聯者
具備調用者傳入的請求對象;
并且綁定接收者。
大家都用過Struts吧?
或許Struts的Action就是一個很好的說明示例:
Public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest req, HttpServletResponse res)
方法的action就是關聯者
方法的req可以理解成請求者
方法的form 就是請求對象
方法的mapping就是接收者