Design patterns 装饰模式与子分类

Design patterns 装饰模式与子分类,design-patterns,decorator,Design Patterns,Decorator,我可以通过添加子分类来解决添加功能的问题,那么我为什么要使用decorator模式呢decorator模式的真正优势是什么?灵活性,这就是我的原因。来自 decorator模式可用于 使扩展(装饰)成为可能 某个对象的功能 在运行时 decorator模式的全部要点是动态添加额外的行为/功能,这在设计时当然是不可能的 同一条: 装饰图案是一种 子类化的替代方法。 子类化增加了编译时的行为 时间,变化影响所有人 原始类的实例; 装饰可以在任何时候提供新的行为 单个对象的运行时 GoF的一个例子:

我可以通过添加子分类来解决添加功能的问题,那么我为什么要使用decorator模式呢decorator模式的真正优势是什么?

灵活性,这就是我的原因。

来自

decorator模式可用于 使扩展(装饰)成为可能 某个对象的功能 在运行时

decorator模式的全部要点是动态添加额外的行为/功能,这在设计时当然是不可能的

同一条:

装饰图案是一种 子类化的替代方法。 子类化增加了编译时的行为 时间,变化影响所有人 原始类的实例; 装饰可以在任何时候提供新的行为 单个对象的运行时

GoF的一个例子:

假设您有一个TextView类。然后在某个地方您需要一个滚动文本视图,所以您可以将TextView子类化并创建ScrolledTextView类。在其他地方,您需要在文本视图周围设置边框。因此,您需要再次子类化并创建BorderedTextView。好吧,现在在某个地方,你需要边界和滚动两者。前两个子类中没有一个同时具有这两种功能。所以你需要创建第三个。创建Scrolled BorderedTextView时,实际上是在重复工作。如果您有任何方法来组合前两个功能,那么就不需要这个类。嗯,事情可能会变得更糟,这可能会导致不必要的班级爆炸

基本上,通过使用decorator模式,您可以在运行时向对象添加任意数量的额外职责,而这些职责是通过子类化无法实现的,而不会潜在地损坏代码结构或为子类添加许多重复的组合

但有一件事,设计模式不是你必须使用的东西。
是否需要一个模式取决于您的特定问题、您是否希望长期维护代码、您是否希望扩展代码以及许多其他类似因素。
没有一种模式在所有情况下都有用。
适合某种情况的图案(装饰图案或其他任何图案)对于另一种情况可能不是一个好的选择

确定了使用装饰器优于子类化的两个主要优点:

  • 比静态更灵活 遗产装饰图案 提供了一种更灵活的方式来添加 对目标的责任超过了我们的能力 具有静态(多个) 遗产和装饰师一起, 可以添加和删除职责 在运行时仅通过 连接和分离它们。在里面 相反,继承要求 为每个类创建一个新类 额外责任(例如:。, 边框滚动文本视图, 边框文本视图)。这就产生了 对许多类和增加 系统的复杂性。此外,, 提供不同的装饰 特定组件的类 类让你混合搭配 责任

    装饰也使添加变得容易 一笔财产两次。比如说 为TextView设置双边框, 只需附加两个边界装饰器。 两次从Border类继承 充其量是容易出错的

  • 避免高性能类 在层次结构中。装饰师提供了一个 按量付费方法添加 责任。而不是尝试 支持所有可预见的功能 在一个复杂的、可定制的类中, 您可以定义一个简单的类和 以增量方式添加功能 装饰对象。功能可以 由简单的片段组成。作为一个 结果,应用程序不需要付费 对于它不使用的功能。它是 也很容易定义新类型的 独立于 它们扩展的对象类,甚至 不可预见的延期。延伸 复杂的类往往会暴露 与项目无关的详细信息 你要增加的责任

  • 在我看来,仅仅防止子类爆炸是非常有说服力的

    如果您有一个
    TextWindow
    ,您希望使用子类将水平滚动、垂直滚动和边框独立地添加到该窗口中,则必须为
    HorizontalScrollingTextWindow
    VerticalScrollingTextWindow
    horizontal和VerticalScrollingTextWindow
    ,定义子类,
    BorderedTextWindow
    水平滚动BorderedTextWindow
    垂直滚动BorderedTextWindow
    水平和垂直滚动BorderedTextWindow
    ,如果您关心滚动和边框的顺序,则更多


    使用Decorators,您只需要定义两个滚动decorator和一个边框decorator。

    子类化可能会导致出现问题。装饰师避免了这一点

    decorator的另一个优点是您正在向接口写入(强制写入)。这使得测试更容易。确实,您的对象层次结构也可以写入接口,因此具有一些相同的优点,但是,我可以单独测试装饰器类的单个实现。我不能对子类执行同样的操作,因为我总是将整个层次结构返回到基类。我无法单独测试新代码

    使用decorator模式并遵循单一责任原则,我可以创建几个decorator并按照我的意愿将它们堆叠起来。我可以在运行时配置它。在继承中,我要么创建每个可能的分支(a->b->c,然后a->c->b,从而复制代码并分解测试数量),要么创建一个层次结构,然后在需要时添加另一个,但这会触发新的测试/发布周期


    这就是为什么您希望使用decorator模式而不是子类化。

    以下是基于实际实现的差异。

    装饰是一种替代外部分类的方式