装饰器模式的继承

Posted

技术标签:

【中文标题】装饰器模式的继承【英文标题】:Inheritance of decorator pattern 【发布时间】:2021-07-18 01:28:41 【问题描述】:

在装饰器模式中,一个抽象类实现一个接口,一个具体类(装饰器)扩展抽象类。如果具体类直接实现接口而不是通过抽象类继承,模式的功能会怎样?

【问题讨论】:

【参考方案1】:

抽象类不是必需的。从 GoF 书的第 179 页开始,

当您只需要添加一个职责时,无需定义抽象的装饰器类。当您处理现有的类层次结构而不是设计新的类层次结构时,通常会出现这种情况。在这种情况下,您可以合并装饰者的职责 用于将组件的请求转发到 ConcreteDecorator。

Head First Design 的一个类似问题是,What is the reason for moving the instance variable into an abstract class in the decorator pattern?

【讨论】:

【参考方案2】:

最初的设计模式一书 (GoF) 于 1994 年出版,使用 C++ 和 SmallTalk 作为示例。 IIRC,C++ 没有语言级接口(至少在 1994 年没有)。当书告诫时

编程到接口,而不是实现

您应该将interface这个词解释为一个概念,而不是一种语言结构。

例如,在 C++ 中,使用专门定义纯虚函数的抽象类来模拟接口是很常见的。 GoF 书中的许多 C++ 示例都是这样做的。

有一个strong relationship between abstract classes and interfaces,实际上它们可以互换。

至于装饰器模式,我猜想总是可以装饰一个界面。例如,考虑这样的界面:

public interface IFace

    void Command(Arg1 arg1, Arg2 arg2);
    Ret1 Query(Arg3);

AFAICT,你可以总是写一个 IFace 的装饰器 - 至少是一个退化的装饰器:

public class MyFace : IFace

    private readonly IFace inner;

    public MyFace(IFace inner)
    
        this.inner = inner;
    

    public void Command(Arg1 arg1, Arg2 arg2)
    
        // Consider doing something interesting here...
        inner.Command(arg1, arg2);
        // ... or here
    

    public Ret1 Query(Arg3)
    
        // Consider doing something interesting here...
        Ret1 ret = inner.Query(arg3);
        // ... or here
        return ret;
    

因此,无论您使用抽象类还是接口,装饰器模式都没有区别。

【讨论】:

以上是关于装饰器模式的继承的主要内容,如果未能解决你的问题,请参考以下文章

浅谈设计模式:装饰器模式|中介模式|原型模式

Java设计模式----------装饰器模式

装饰器模式及JAVA IO流例子★★★☆☆

装饰器模式

装饰器模式

二十三种设计模式之装饰器模式