也许我在这里遗漏了一些东西,我承认我的OO技能不是我想要的,但是看看这个example of the decorator pattern,我注意到UML声明了装饰器既是一个组件又是一个组件。这让我感到困惑,因为它似乎是多余的,因为它是两者,事实上,当我测试现实世界时#34;代码,found here,并修改装饰器类,如下所示:
abstract class Decorator /*: LibraryItem*/ {
protected LibraryItem libraryItem;
// Constructor
public Decorator(LibraryItem libraryItem) {
this.libraryItem = libraryItem;
}
public /* override */ void Display() {
libraryItem.Display();
}
}
...
class Borrowable : Decorator {
protected List<string> borrowers = new List<string>();
// Constructor
public Borrowable(LibraryItem libraryItem) : base(libraryItem) { }
public void BorrowItem(string name) {
borrowers.Add(name);
libraryItem.NumCopies--;
}
public void ReturnItem(string name) {
borrowers.Remove(name);
libraryItem.NumCopies++;
}
public new /*override*/ void Display() {
base.Display();
foreach (string borrower in borrowers) {
Console.WriteLine(" borrower: " + borrower);
}
}
}
我在这里所做的只是通过评论&#34;:LibraryItem&#34;来删除is-a关系。但通过保持&#34; protected LibraryItem libraryItem;&#34;来保持has-a关系。我还注释掉了Display方法的覆盖,用new关键字替换了一个。我可以说,这与原始代码一样有效。
我在这里遗漏了什么吗?装饰器是否真的需要从组件继承? UML图和实现的代码肯定会这样建议,但我很好奇是否有我没有看到或正确处理的东西。
思想?
答案 0 :(得分:3)
装饰器模式假设为
动态地将附加职责附加到对象。 装饰器为子类化提供了灵活的替代扩展 功能。这种模式的设计使得多个装饰器可以堆叠在每个装饰器的顶部 另外,每次都向被覆盖的人添加新功能 方法(一个或多个)。
实际上,如果你的装饰器类继承了它正在装饰的相同类型,那么可以链接越来越多的装饰器,从而增加了越来越多的责任,同时仍然能够在调用原始基类的地方使用它。
例如,在您的示例中需要LibraryItem的地方,您将无法传递Borrowable。您的示例只是一个组合示例,而不是装饰器示例。
查看C#Stream及其装饰器。
让我们举例说我有一个Document类。现在我可以拥有一个DocumentWithSpellCheckingDecorator和DocumentWithGrammarCheckingDecorator。我可以使用两个装饰器或只使用其中一个,但我仍然会有一个Document并且可以用作Document,因为我只是用更多功能装饰它。也许这不是一个完美的例子,但希望它有所帮助。
顺便说一下,dofactor网站很容易理解,但有时并不能完全传达信息。我也在网站上的其他模式中找到了这个。
答案 1 :(得分:2)
装饰组件 IS-A 组件,例如BorderedImage
是用边框修饰的图像,它可以在任何地方使用{{1} {{1} 1}}将使用超类。
这意味着Image
可以传递给使用BorderedImage
的任何代码,例如调用Image
的方法。
打破saveImage(Image image)
和BorderedImage
之间的继承关系会阻止在带有Image
的代码中使用装饰图像。
这意味着Image
不再仅仅是BorderedImage
。因此,保持继承关系对于保持Decorator模式的意义至关重要。