装饰图案与继承和组成

时间:2014-03-25 21:29:30

标签: c# design-patterns decorator

也许我在这里遗漏了一些东西,我承认我的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图和实现的代码肯定会这样建议,但我很好奇是否有我没有看到或正确处理的东西。

思想?

2 个答案:

答案 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模式的意义至关重要。