![](/img/trans.png)
[英]How do you create a mock/substitute when you don't want to expose an instance of a class?
[英]How do you implement the Decorator pattern if you can't inherit from the class you want to decorate?
這更像是一個設計問題......如果出現以下情況,您無法進行裝飾設計模式:
1)對象標記為“密封”,意味着您無法從中擴展。 2)或者你想要覆蓋一個方法,但它不是虛擬的。
那你能做什么? 如果您沒有源代碼(如第三方庫),則無法更改類源代碼。
Decorator模式不需要繼承。 最簡單的情況是,您要裝飾的對象是否實現了接口。 然后你的裝飾者可以簡單地實現相同的接口:
[ IWindow ]
[ + Draw() ]
---------------
|
+--- [ Window ]
| [ + Draw() ]
|
|
+--- [ DecoratedWindow ]
[ + Draw() ]
-------------------
|
+--- [ BorderDecorator ]
|
+--- [ VerticalScrollbarDecorator ]
|
+--- [ HorizontalScrollbarDecorator ]
現在你可以這樣做:
IWindow w = new BorderDecorator(
new HorizontalScrollBarDecorator(
new VerticalScrollBarDecorator(
new Window(80, 24))));
// This is a window with a border and scrollbars, even though
// the original Window class has no idea what those are.
w.Draw();
可能的具體細節將取決於您嘗試裝飾的類的確切性質。
您可以采取多種方法,具體取決於您對實際代碼的控制程度:
1)您是否將密封類的實例傳遞給第三方代碼? 如果是這樣,除了祈禱你的第三方接受一個界面而不是具體的對象之外,你無能為力。
它完全有可能在CLR中編寫鈎子來攔截密封類中的方法,這就是一些模擬框架如何模擬非虛方法和密封類。 我不建議這樣做,因為您的第三方代碼是針對對象的特定實現編寫的,並且在第三方代碼的鼻子下交換實現可能會產生非平凡的,未定義的后果。
2)您是否在自己的代碼中使用密封類? 如果是這樣,那就去吧小工具包裝! 使用與密封類相同的公共方法創建一個非密封類,公共方法應該傳遞給密封對象,然后根據需要覆蓋類的功能。
3)您是否擁有密封類的代碼? 如果是這樣,找到類定義,雙擊'sealed'關鍵字以突出顯示它,根據需要點擊刪除鍵;)或者可以用相同的公共方法替換接受密封對象的接口的方法。
您可以創建自己的類來包裝第3方類並裝飾該類。 您的類將使用包裝的類實現。 包裝類充當適配器。
如果你不能繼承並且原始類沒有實現你也可以在你的裝飾器上實現的任何接口,那么我相信你應該嘗試代理類或適配器。 如果那也不可能,那么,你總是有一個“替代技術資源”:你可以定義一個轉換運算符,允許將裝飾器轉換為原始的(盡管我認為這不是一個很好的選擇)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.