資源描述:
《委托模式:委托模式》由會員上傳分享,免費在線閱讀,更多相關內容在行業(yè)資料-天天文庫。
1、委托模式撰文/透明梗概委托是對一個類的功能進行擴展和復用的方法。它的做法是:寫一個附加的類提供附加的功能,并使用原來的類的實例提供原有的功能。場景擴展和復用一個類的功能常用的一種方法是繼承,而另一種更普遍的方法則是委托。在很多情況下委托很適用,而繼承則并不適用。另外在[MEYERS98]中也講到,公有繼承表現的設計思想是1“is-a-kind-of”,私有繼承表現的設計思想則是“is-implemented-in-terms-of”,這些關系都是靜態(tài)的、不能在運行時改變的。而在一些情況下我們需要表現的設計思想是“is-a-rol
2、e-played-by”的關系,在這些情況下不應該用繼承的方法。下面用一個例子來幫助說明。假設我們?yōu)橐粋€航空公司設計軟件系統,于是我們必須用一些類來表示各種各樣的“人”,包括機組人員、售票員、旅客等等。一種思路是這樣:因為這些人都是抽象的“人”,因此設計一個Person抽象類,并從這個抽象類衍生出我們需要的各種類。由此我們得到下面的類圖:圖1:用繼承的方法建模這個設計方案的問題是很明顯的:一個機組人員在休假的時候可能乘坐飛機而成為一個旅客;航空公司也可能把機組人員調去做售票員??是的,一個人可能成為三種角色中的任何一種。如果我們
3、一定要堅持繼承的思路,那么我們可能得到下面這個圖:(見下頁圖2)1[MEYERS98]的ITEM35指出,public繼承表示“is-a”的關系,也就是這里所說的“is-a-kind-of”。1很明顯我們遇到了“類爆炸”的問題。我們這里只有三個角色,就需要用七個衍生類來表現所有的情況。如果我們有六個角色呢?我們將需要63個衍生類。(我畫圖2用了15分鐘的時間,如果要畫63個衍生類??呵呵,呵呵)而且即使使用了這么多衍生類,我們仍然有困難。因為繼承所表現的“is-a-kind-of”關系是靜態(tài)的,在編譯時就固定了。而一個“人”可能
4、在不同的時間扮演不同的角色,于是我們可能需要用多個對象來表現同一個“人”的不同角色,這也是一件相當麻煩的事情。而另一方面,如果我們用委托的方式來表現這個問題,我們可以得到一個相當優(yōu)雅的解決方案,上面提到的問題都自然的解決了。這樣的解決方案如圖3所示:圖2:繼承解決方案的發(fā)展(類爆炸的實例)圖3:使用委托的建模2約束如果你發(fā)現一個對象需要在不同的時間“成為”不同的衍生類,那么首先這個對象根本不應該“是”一個衍生類。因為一個對象一旦作為衍生類被創(chuàng)建出來,它就只能是這個衍生類的實例而不能扮演其他角色了。另一方面,一個對象可以在不同的時
5、間把不同的行為委托給不同的對象。如果你發(fā)現一個衍生類在試圖隱藏其超類的方法或變量,這說明這個類根本不應當從這個超類衍生得到,因為根本沒有什么合理的理由來隱藏超類的方法或變量。但另一方面,如果使用委托的設計方法,你就可以隨意選擇需要的方法或變量。把一個類設計成現有的具體類的衍生類也不是一件值得推薦的事情。(這個話題的C++版本在[MEYERS96]中有非常詳細的介紹,因此我就不在這里贅言了。)“不適當的繼承”在實際中被如此廣泛的應用,以至于可以把它們歸納成一種“反模式(antipattern)”了。正如上面所說的,繼承一個具體類可
6、能導致各種無法預料的問題。實際上,可能絕大多數對類的功能的擴展和復用都不應該使用繼承。解決方案委托是對類的行為進行復用和擴展的一條途徑。它的工作方式是:包含原有類的實例引用,實現原有類的接口,將對原有類方法的調用轉發(fā)給內部的實例引用。圖4展示了本模式的一般形式:圖4:使用委托模式對類的行為進行復用和擴展委托的用途比繼承更加廣泛。用繼承能實現的對類的任何形式的擴展都可以用委托的方式完成。因此在[GoF]中也建議盡量用委托代替繼承。參與者lDelegator(委托者)-保存Delegate的實例引用。-實現Delegate的接口。-
7、將對Delegate接口方法的調用轉發(fā)給Delegate。lDelegate(受委托者)-接受Delegator的調用,幫助Delegator實現其接口。效果3使用委托模式可以避免繼承方法遇到的問題。另外,使用委托模式可以很容易的在運行時對其行為進行組合。委托模式的主要缺點是類之間的聯系、類體系結構不如繼承那樣清楚明顯。不過也有一些方法可以改善這些聯系的清楚程度。l使用一致并且清楚的名稱,讓程序的讀者可以直觀的知道Delegator和Delegate之間的聯系。比如說,如果用一個類來代理一些Widget衍生類的創(chuàng)建,那么把這個類
8、命名為WidgetFactory就是不錯的方法。l在程序中寫上適當的注釋,告訴讀者:這里使用委托模式。l遵循LawofDemeter模式[GRAND99],即:如果兩個類之間只有間接聯系,采用間接委托;如果有直接聯系,采用直接委托。這可以減少類之間的聯系數量。l