也许我在这里丢失了一些东西,我承认我的OO技能不是我想要的,但是看着这个example of the decorator pattern,我注意到UML声明装饰器既是-组件又具有-一个组件。这让我有些困惑,因为两者似乎都是多余的,而且实际上,当我测试“真实世界”代码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);
}
}
}
我在这里所做的只是通过注释掉“:LibraryItem”来删除is-a关系,而通过保留“ protected LibraryItem libraryItem;”来保持has-a关系。我还注释掉了Display方法上的重写,将其替换为new关键字。据我所知,它的工作原理和原始代码一样好。
我在这里想念什么吗?装饰器是否真的有必要继承组件? UML图表和已实现的代码肯定会建议这样做,但是我很好奇是否有某些我看不到或无法正确解决的问题。
有什么想法吗?
最佳答案
装饰器模式假定为
动态地将附加职责附加到对象。
装饰器为子类扩展提供了灵活的替代方法
功能。设计此模式是为了使多个装饰器可以堆叠在每个装饰器的顶部
其他,每次向覆盖的对象添加新功能
方法)。
实际上,如果您的装饰器类继承自它正在装饰的同一类型,则可以链接越来越多的装饰器,从而增加越来越多的责任,同时仍然可以在调用原始基类的地方使用它。
例如,您将无法在示例中需要LibraryItem的地方传递Borrowable。您的示例只是一个合成示例,而不是一个装饰器示例。
看一下C#Stream及其装饰器。
例如,假设我有一个Document类。现在,我可以有一个DocumentWithSpellCheckingDecorator和DocumentWithGrammarCheckingDecorator。我可以使用两个装饰器,也可以只使用其中一个,但是由于我只是用更多的功能装饰了它,所以我仍然会有一个Document并可以用作Document。也许这不是一个完美的例子,但希望对您有所帮助。
顺便说一下,dofactor网站很容易理解,但有时并不能很好地传达信息。我也在网站上的其他模式中找到了这一点。