【读书笔记】设计模式沉思录
當(dāng)我在china-pub上看到這本書的預(yù)售消息后就下訂單了,不知道多少日子之后收到了china-pub的郵件。不過書到手后我好失望,怎么才140頁~~~忽悠誰呢。
抱著濃縮的都是精華的心態(tài),我看下去了,今兒終于給看完了,趁著還有幾分熱度趕快給記錄下來。
這本書的內(nèi)容主要來自John Vlissides(Gof之一)為C++ Report寫的一些小文,然后經(jīng)過整理調(diào)整組織成本書。可惜的是John英年早逝(于2005年11月24日因腦瘤病故,享年44歲),不然我想留下的佳作也許更多。
書是葛子昂翻譯的,質(zhì)量上乘,從中文來看本書原文肯定就很有趣,很難翻譯,可翻譯后的中文卻如此流暢,佩服佩服。
書的第一章就來個下馬威:對模式的十大誤解。第一誤解就直指亞歷山大對模式的定義:模式就是在一種場合下對某個問題的一個解決方案。作者還舉了個非常詼諧的例子來證明這種誤解。
后面幾條大部分在闡述這么一個道理:模式不是圣經(jīng)、模式不是萬能鑰匙、模式不是救世主、模式也不限于面向?qū)ο箢I(lǐng)域。
篇幅最多的當(dāng)屬本書第二章,運用模式進行設(shè)計。作者用大家都熟悉的計算機的層次文件系統(tǒng)作為例子,用模式來為應(yīng)用開發(fā)人員設(shè)計一個編程模型(API)。
首先要建模出這種層次文件系統(tǒng)的結(jié)構(gòu),當(dāng)屬組合模式(Composite)莫屬:文件夾(Composite)、文件(Leaf)。
然后新的需求來了,我們要在這種文件系統(tǒng)中添加對快捷方式的支持,快捷方式實際上就是指向?qū)嶋H文件或者文件夾的一個鏈接,當(dāng)然,我們可以將其也作為一個Leaf處理,不過和真實的文件不同,比如刪除快捷方式不會刪除對應(yīng)的文件。如是這里引入了代理模式(Proxy)。
隨著文件系統(tǒng)越來越完善,提供的功能也勢必增多,這個時候就要給這個層次結(jié)構(gòu)中的一些類添加各種接口,這個結(jié)構(gòu)勢必就變得越來越臃腫。那如何在不修改層次結(jié)構(gòu)中的類就可以添加新的操作呢?這個時候引入了訪問者模式(Visitor)。注意這里Visitor模式的用法,提供多個visit重載,將運行時綁定提前到編譯時綁定,并且提供一個通用的visit,可以處理所有為預(yù)設(shè)的操作。
不過使用Visitor的時候要注意的是,你的這個結(jié)構(gòu)必須穩(wěn)定,比如我們這里就只有文件夾、文件、快捷方式三種,在可預(yù)見的未來是比較穩(wěn)定的,如果我們要往這其中添加一個新的該怎么辦?那Visitor就有點尷尬了。
然后在為了對文件系統(tǒng)進行保護的時候,由于有些方法,比如對文件系統(tǒng)read時,安全授權(quán)是通用的,但是對文件夾、文件、快捷方式的實現(xiàn)各不相同,在這里引入了模板方法設(shè)計模式(Template Method)。模板方法設(shè)計模式是進行框架程序設(shè)計時最常用的模式,它可以實現(xiàn)反向的控制,比如我們的ASP.NET中,頁面的處理流程是固定的,但是每個頁面的實現(xiàn)卻不相同,通過模板方法設(shè)計模式,將相同的部分放到Page類里,然后不同的部分定義為虛方法,提供給子類(也就是我們具體的頁面)實現(xiàn),比如OnLoad方法。
現(xiàn)代的文件系統(tǒng)基本上都是基于多用戶的,這就需要對登錄用戶的訪問,來看看該用戶是否對該文件或文件夾有訪問的權(quán)限,在這里引入了單件模式(Singleton)。這里還提供了如何設(shè)計允許有多個實例的Singleton的方案。
有了用戶,當(dāng)然就有用戶組的概念了,而且常識告訴我們,一個用戶可以屬于多個分組,一個分組里也有多個用戶,這就是一種多對多的關(guān)系,如果直接把這種關(guān)系建立在User和Group對象本身,勢必帶來不必要的麻煩。在這里作者又引入了中介者模式(Mediator)。
就這樣這個文件系統(tǒng)的編程模型終于設(shè)計完畢了,總共涉及了Composite、Proxy、Visitor、Template Method、Singleton、Mediator等六個模式。而且在設(shè)計當(dāng)中,作者還用實例告訴我們?nèi)绾螐哪J搅斜碇羞x擇一個合適的模式。
第三章標(biāo)題為主體和變體,不過還沒有理解這個名字的含義。。。。
開篇作者就問,Singleton這個模式為啥從來都沒有涉及刪除的問題呢?誰來刪除Singleton?是有意的回避么?最后作者給出了解決方案,不過方案看看就可以了,對.Net等有GC的平臺,沒有明確銷毀的析構(gòu)函數(shù),作者的解決方案基本上無效。
實際上在.Net里,Singleton也基本上是不可能刪除的,使用了類成員,除非你unload應(yīng)用程序域。作者的方案實際上后來在C++的標(biāo)準(zhǔn)庫里出現(xiàn)了,就是所謂的auto_ptr。
后來作者在這里公開了一個未出現(xiàn)在《設(shè)計模式》這本書里的一個模式:Generation Gap模式,作者的說法是當(dāng)時沒有找到該模式的應(yīng)用實例,選到《設(shè)計模式》這本書里的所有模式,必須要在現(xiàn)實中找到兩個實例才行。
這個模式是這樣的,當(dāng)我們用設(shè)計工具設(shè)計界面,然后工具自動生成界面的代碼,但是我們又要給這些界面編寫一些行為,那如果后來要修改界面的時候,工具就會重新生成那些代碼,如果我們自己編寫的行為代碼和界面代碼放到一起,那我們寫的代碼勢必會被工具給覆蓋了,如是就提出了這么個解決方案:
CoreClass就是工具生成的描繪界面的代碼,ExtensionClass是我們自己編寫的行為的代碼。看到這個東東你是不是想到WinForm里的Form.designer.cs和Form.cs?.Net里用分部類完美的解決了這個問題,Form.designer.cs里放的是工具(Visual Studio)生成的界面代碼,Form.cs是我們寫的邏輯代碼。只是這里結(jié)構(gòu)變了,在編譯時Form.designer.cs和Form.cs會合并成一個類,而沒有了繼承關(guān)系。
Type Laundering
Laundering,有淡化洗滌的意思。說的是這樣的:
public void? Do(Node n)
{
?
}
Do方法接收的是一個基類,該基類下還有很多具體類。但是在這個傳遞過程中,這些具體類的信息都丟失了,在Do方法里為了訪問Node某個具體類的特有的功能,必須向下轉(zhuǎn)型,我們都知道向下轉(zhuǎn)型是個非常惡心而且非常不安全的做法,在編譯時根本發(fā)現(xiàn)不了,或許就到運行時來個崩潰。
這本來是一個缺點,但是作者話鋒一轉(zhuǎn),卻在另一個場景里利用這個缺點給出了一個非常完美的方案。
大家都知道,在迭代器模式里,我們有這么兩個參與者:Subject(被迭代的對象),Cursor(一個游標(biāo))。不同的Subject,比如Hashtable、List等都有對應(yīng)的Cursor,而且這些Cursor只能被對應(yīng)的Subject訪問,比如你就在外面的代碼中實例化一個Cursor,然后訪問里面的東東,這沒有任何意義嘛,脫離了容器的存在,你的游標(biāo)游到哪里呢?
為了只能讓對應(yīng)的Subject訪問到對應(yīng)的Cursor,如是我們把Cursor里的信息都隱藏起來(private),但是這樣一來Subject如何訪問了呢?好辦,將Subject作為Cursor的友元類(.Net里不能添加友元類,但可以有友元程序集,關(guān)于C++的友元,可以這么理解,比如A是B的友元,那么A就可以訪問B的私有成員)。C++里用friend關(guān)鍵字來聲明友元,但是有個問題是friend不能繼承,也就是在父類里聲明了友元,子類里并不能繼承到,這就麻煩了。
這里我們就遇到了一個矛盾,為了防止Cursor的信息泄露,被“無知”的客戶代碼濫用,我們將Cursor的信息private起來,但是又必須讓Subject可以使用,如是引入了friend,但是friend又不能被繼承。這可咋辦呢?
如是這里引入了一個抽象的基類Cursor,抽象的基類是不可以實例化的啊,而且這個抽象基類只有一個公有的析構(gòu)函數(shù),構(gòu)造函數(shù)是私有的,其余啥也沒有,然后我們的具體的Cursor,比如ListCursor就從Cursor派生,但是我們要使用到ListCursor的功能,就必須先將Cursor向下轉(zhuǎn)型為ListCursor,然后可以使用,假設(shè)我們這里的容器類是List,List肯定是“知道know”ListCursor的,而我們的客戶代碼,卻不知道ListCursor,就無法做這個轉(zhuǎn)型,所以就濫用不了這里的游標(biāo)了。
其實這里的做法就是利用繼承作為一種封裝手段,屏蔽掉子類的信息。回憶我們大部分對繼承、接口等的應(yīng)用,實際上大部分時候我們都不是要實現(xiàn)復(fù)用的目標(biāo)。這里的例子也很好的體現(xiàn)了這一點。
不過值得一提的是,在C#中,我們有了嵌套類,我們可以把這個游標(biāo)實現(xiàn)容器類的內(nèi)部,又將信息隱藏推進了一步。
第四章叫愛的奉獻(xiàn),不知道為啥叫這么個名字,呵呵。
討論的是Multicast這又一沒有出現(xiàn)在《設(shè)計模式》這本書中的模式,在這一章中精彩的是Gof四個人關(guān)于這個模式的一些爭論。Multicast是觀察者模式的兄弟,有幾分相似,但又有一些微妙的不同,要問什么是Multicast模式?實際上.Net現(xiàn)在使用的事件機制就是這種模式~~~所以也就不在這里羅嗦了~~
?
書很不錯,就是篇幅太短了,看得不過癮。還有一點是,如果你要看這本書,必須先對《設(shè)計模式》這本書有個了解,書中很多討論會引用《設(shè)計模式》這本書里的一些東西。突然想起來有人在china-pub上的留言:大師已逝,墨跡留香。
轉(zhuǎn)載于:https://www.cnblogs.com/yuyijq/archive/2010/06/02/1750391.html
總結(jié)
以上是生活随笔為你收集整理的【读书笔记】设计模式沉思录的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JPBC库只使用椭圆曲线群,不使用双线性
- 下一篇: 数据分析即未来