簡體   English   中英

在裝飾器對象上調用未裝飾的方法

[英]Calling non-decorated methods on decorator object

假設我們已經實現了裝飾器模式 ,如下圖所示。 使用CondimentDecorator類,可以裝飾Beverage類。 方法cost()getDescription()會注意這一點。

在此處輸入圖片說明

當創建如下所示的裝飾飲料時 ,調用方法getName()不適用於裝飾對象。 為了完成這項工作,還應該將該方法放在CondimentDecorator類中,並將調用委托給組合的Drink變量。

Beverage b = new Milk(new Espresso("A very nice espresso"));
b.getName() // returns null

當有很多不需要修飾的方法時,所有這些方法也都應該放在CondimentDecorator中以簡單地委派。 因此問題是: 解決此“問題”的一種整潔(通常被接受)的方法是什么?

對於像Java或C#這樣的靜態類型語言(是的,C#不是完全靜態類型的,我知道DLR和動態的),這種“問題”的普遍接受的方法是讓裝飾方法明確地委派給裝飾對象。 該解決方案具有簡單明顯的利益。

在您的示例中,如果不重寫getName則意味着您更改裝飾對象的行為,這正是裝飾器模式的目的。

如果您選擇默認情況下委托給裝飾對象則它看起來好像繼承已中斷,因為CondimentDecorator繼承自Beverage,但未使用基類的方法。

然后,要更改此行為,您將需要以某種方式定義未委托給裝飾對象的方法,但應“照常繼承”工作。 那將是不明顯的並且非常混亂。

話雖如此,您想要實現的目標應該可以在Java中實現。

例如,在.NET中,您可以通過以下方式進行操作,我相信Java具有類似的功能

  1. 通過生成使用繼承來動態修改對象行為的動態運行時代理,請參閱城堡動態代理。
  2. 通過使用MSIL重寫技術,該技術在編譯時重寫您的中間代碼以對其進行修改,例如,請參見Fody-方法裝飾器

此外,請檢查原型繼承在JavaScript中的工作方式-該行為與您要實現的行為非常相似

在您的情況下,如果只有幾個operation1(),可以將委托調用添加到CondimentDecorator。 如果只有很少的call()需要裝飾,則可以在需要時制作裝飾器,例如:DecoratorFactory.make(new Milk(new Espresso(“ Espresso”)))。getDescription();

要么

CondimentDecorator.getDescription(new Milk(new Espresso(“ A a great nice espresso”))));

重點:模式為您服務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM