也许我在这里丢失了一些东西,我承认我的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网站很容易理解,但有时并不能很好地传达信息。我也在网站上的其他模式中找到了这一点。

10-07 19:47
查看更多