装饰者模式与子分类

Gai*_*ter 52 design-patterns decorator

我可以通过添加子类来解决添加功能的问题然后为什么我应该使用装饰模式什么是装饰模式的真正优势?

tas*_*oor 46

GoF的一个例子:

假设您有一个TextView类.然后在某些地方你需要一个滚动的文本视图,所以你继承TextView并创建ScrolledTextView类.在其他一些地方你想要一个文本视图边框.所以你再次创建子类并创建BorderedTextView.好吧,现在在某个地方你想要边框和滚动两者.前两个子类中没有一个具有这两种能力.所以你需要创建第三个.创建ScrolledBorderedTextView时,实际上是在复制工作量.如果您有任何方法可以构成前两个的功能,则不需要此类.嗯,事情可能会变得更糟,这可能导致不必要的阶级爆炸.

基本上,通过使用装饰器模式,您可以在RUN TIME向对象添加任意数量的附加责任,这是通过子类化无法实现的,而不会潜在地破坏您的代码结构.

但有一点,设计模式不是你必须使用的东西.是否需要模式取决于您的特定问题,您希望长时间维护代码,是否要扩展代码以及许多其他因素.并且没有任何模式在所有情况下都有用.适合某种情况的模式(装饰者或任何其他)可能不是另一种情况的好选择.


slo*_*oth 43

来自维基百科的装饰模式

装饰器模式可用于使得可以在运行时扩展(装饰)某个对象的功能.

装饰器模式的重点是动态添加其他行为/功能,这在设计时当然是不可能的.

来自同一篇文章:

装饰器模式是子类化的替代方案. 子类在编译时添加行为,并且更改会影响原始类的所有实例; 装饰可以在运行时为单个对象提供新的行为.

  • 我也必须在设计中创建装饰器类.所以我以类似的方式添加子类,所以重点是什么. (11认同)
  • 维基百科上的文章提供了一些例子.当然,您必须在设计时创建装饰器类,您可以选择在运行时动态应用它们. (4认同)
  • @Gainster确实,你是对的。装饰器的最大优点是可以为其他类重用此类装饰器。正如其他人在该线程中所说的那样。 (2认同)

Don*_*oby 20

GoF的设计模式一书标识使用装饰在子类中两个主要的优点:

  1. 比静态继承更灵活. 与静态(多个)继承相比,Decorator模式提供了一种更灵活的方式来向对象添加职责.使用装饰器,可以在运行时添加和删除职责,只需通过附加和分离它们即可.相反,继承需要为每个额外的职责创建一个新类(例如,BorderedScrollableTextView,BorderedTextView).这会产生许多类并增加系统的复杂性.此外,为特定的Component类提供不同的Decorator类可以让您混合和匹配职责.

    装饰器还可以轻松添加两次属性.例如,要为TextView提供双边框,只需附加两个BorderDecorators即可.从Border类继承两次充其量是容易出错的.

  2. 避免在层次结构中高高的功能级别的类.Decorator提供了一种即付即用的方法来增加责任.您可以定义一个简单的类,并使用Decorator对象逐步添加功能,而不是尝试支持复杂的可自定义类中的所有可预见功能.功能可以由简单的部分组成.因此,应用程序无需为不使用的功能付费.即使对于不可预见的扩展,也可以很容易地从它们扩展的对象类中独立定义新类型的装饰器.扩展复杂类往往会暴露与您要添加的职责无关的详细信息.

从我的观点来看,单独防止子类爆炸非常引人注目.

如果你有一个TextWindow对您想要的所有独立和选择添加水平滚动,垂直滚动和边框,使用子类,你必须定义子类HorizontalScrollingTextWindow,VerticalScrollingTextWindow,HorizontalAndVerticalScrollingTextWindow,BorderedTextWindow,HorizontalScrollingBorderedTextWindow,VerticalScrollingBorderedTextWindow,HorizontalAndVerticaScrollingBorderedTextWindow,和更多,如果你关心的秩序滚动和接壤.

使用装饰器,您只需要定义两个滚动装饰器和一个边框装饰器.


小智 11

子类化可能导致Liskov替换原则的问题.装饰者避免了这一点.

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

使用装饰器模式并遵循单一责任原则,我可以创建几个装饰器并按我希望的方式堆叠它们.我可以在运行时配置它.在继承中,我要么必须创建每个可能的分支(a-> b-> c然后a-> c-> b,从而复制代码并爆炸测试数量),或者我创建1个层次结构然后在需要时添加另一个,但是这会触发新的测试/发布周期.

这就是您希望使用装饰器模式而不是子类化的原因.


She*_*ngh 5

这是基于实际实现的差异。

装饰是子类化的另一种方法,用于扩展现有类的功能。这是我们应该使用子类或装饰器的一些场景。

1)子类主要用于扩展相似类组的功能,希望在子类中保留旧功能和新功能,并且子类的所有实例共享相同的功能。如果我们对子类进行更改,那么它将反映子类的所有实例。例如层次关系,相似的类组。

父母->孩子->孙子。

汽车->Maruti 800->Maruti 100(将具有Maruti 800 以及新车型的功能)

2)装饰器模式用于装饰现有的类,而不改变旧的行为。例如一个类圆圈有普通边框,但我们需要用红色边框装饰它,一段时间后,有些用户想要黄色的圆圈,有些用户想要圆形有绿色边框,有些用户想要红色和黄色边框圆圈,有些用户想要红色和绿色边框圆圈等,因为这是完美的模式,因为它会减少组合类的数量。下面是示例。

Icircle cir=new RedDecorator(new Circle()) 用红色装饰圆圈

Icircle cir=new YellowDecorator(new Circle()) 用黄色装饰圆

Icircle cir=new RedDecorator(new YellowDecorator(new Circle())) 装饰

红色和黄色的圆圈,这里我们不需要创建RedAndYellow类装饰器。同样,我们可以用其他组合来装饰圆圈,而无需创建新的组合类集。

这样就减少了组合类的数量。

这是装饰器模式的有用链接

https://www.tutorialspoint.com/design_pattern/decorator_pattern.htm