装饰器模式与子类化

发布于 2024-10-14 23:50:01 字数 55 浏览 3 评论 0原文

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

I can solve the problem of adding functionality by adding sub classing then why should I use decorator pattern what's the real advantage of decorator pattern ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

三生路 2024-10-21 23:50:02

GoF 设计模式一书指出了使用装饰器相对于子类化的两个主要优点:

  1. 比静态更灵活
    继承。
    装饰器模式
    提供了更灵活的添加方式
    对对象的责任超过可以
    具有静态(多个)
    遗产。有了装饰器,
    可以添加职责并
    只需在运行时删除
    安装和拆卸它们。在
    相比之下,继承需要
    为每个创建一个新类
    额外的责任(例如,
    有边框的可滚动文本视图,
    有边框的文本视图)。这就产生了
    到许多班级并增加
    系统的复杂性。此外,
    提供不同的Decorator
    特定组件的类
    课程让你可以混合搭配
    职责。

    装饰器也使得添加变得容易
    一个财产两次。例如,要
    给 TextView 一个双边框,
    只需附加两个 BorderDecorators 即可。
    两次继承 Border 类
    充其量是容易出错。

  2. 避免高层的功能丰富的类
    装饰器提供了一个
    即用即付方式添加
    责任。而不是尝试
    支持所有可预见的功能
    在一个复杂的、可定制的类中,
    你可以定义一个简单的类并且
    增量添加功能
    装饰器对象。功能可以
    由简单的部分组成。作为一个
    结果,申请无需付费
    对于它不使用的功能。它是
    也很容易定义新的种类
    装饰器独立于
    他们扩展的对象类,甚至
    对于不可预见的扩展。延伸
    复杂的类往往会暴露
    与本案无关的细节
    您要添加的职责。



从我的角度来看,仅防止子类爆炸就非常引人注目。

如果您有一个 TextWindow,您想要使用子类独立且可选地向其中添加水平滚动、垂直滚动和边框,则必须为 Horizo​​ntalScrollingTextWindow 定义子类, VerticalScrollingTextWindow, Horizo​​ntalAndVerticalScrollingTextWindow, BorderedTextWindow, Horizo​​ntalScrollingBorderedTextWindow, VerticalScrollingBorderedTextWindow, Horizo​​ntalAndVerticaScrollingBorderedTextWindow,如果您关心滚动和边框的顺序,还有更多。

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

The GoF Design Patterns book identifies two major advantages of using Decorators over subclassing:

  1. More flexibility than static
    inheritance.
    The Decorator pattern
    provides a more flexible way to add
    responsibilities to objects than can
    be had with static (multiple)
    inheritance. With decorators,
    responsibilities can be added and
    removed at run-time simply by
    attaching and detaching them. In
    contrast, inheritance requires
    creating a new class for each
    additional responsibility (e.g.,
    BorderedScrollableTextView,
    BorderedTextView). This gives rise
    to many classes and increases the
    complexity of a system. Furthermore,
    providing different Decorator
    classes for a specific Component
    class lets you mix and match
    responsibilities.

    Decorators also make it easy to add
    a property twice. For example, to
    give a TextView a double border,
    simply attach two BorderDecorators.
    Inheriting from a Border class twice
    is error-prone at best.

  2. Avoids feature-laden classes high up
    in the hierarchy.
    Decorator offers a
    pay-as-you-go approach to adding
    responsibilities. Instead of trying
    to support all foreseeable features
    in a complex, customizable class,
    you can define a simple class and
    add functionality incrementally with
    Decorator objects. Functionality can
    be composed from simple pieces. As a
    result, an application needn't pay
    for features it doesn't use. It's
    also easy to define new kinds of
    Decorators independently from the
    classes of objects they extend, even
    for unforeseen extensions. Extending
    a complex class tends to expose
    details unrelated to the
    responsibilities you're adding.

From my point of view, preventing subclass explosion alone is quite compelling.

If you have a TextWindow to which you want to add horizontal scrolling, vertical scrolling, and borders all independently and optionally, using subclasses, you'd have to define subclasses for HorizontalScrollingTextWindow, VerticalScrollingTextWindow, HorizontalAndVerticalScrollingTextWindow, BorderedTextWindow, HorizontalScrollingBorderedTextWindow, VerticalScrollingBorderedTextWindow, HorizontalAndVerticaScrollingBorderedTextWindow, and more if you care about the order of scrolling and bordering.

With Decorators, you only need to define two scrolling decorators and one border decorator.

梦途 2024-10-21 23:50:02

子类化可能会导致里氏替换原则出现问题。装饰器避免了这种情况。

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

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

这就是为什么您想要使用装饰器模式而不是子类化。

Subclassing can lead to issues with the Liskov substitution principle. The decorator avoids this.

Another advantage of the decorator is that you are writing (forced to write) to an interface. This makes things easier for testing. It is true that your object hierarchy can also be written to an interface and thus have some of the same advantages, however, I can test a single implementation of a decorator class in isolation. I cannot do the same with a subclass because I will always get the whole hierarchy back to the base class. I am unable to test the new code in isolation.

Using the decorator pattern and following the single responsibility principle, I can create several decorators and stack them anyway I wish. I can configure that at runtime. In inheritance I either have to create every possible branch (a->b->c then a->c->b, thus duplicating code and exploding the number of tests), or I create 1 hierarchy then add another when needed, but this triggers a new test/release cycle.

This is why you would want to use the decorator pattern instead of subclassing.

一个人的旅程 2024-10-21 23:50:02

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

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

1)子类主要用于扩展类似功能的情况
一组想要保留旧功能和新功能的类
在子类中
并且子类的所有实例共享相同的功能。如果我们
更改子类,然后它将反映所有实例
子班的数量。例如
层次关系,类似的类组。

父母->孩子->孙子。

Car->Maruti 800->Maruti 100(将具有 Maruti 800 和 New 的功能)

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

Here is the differences based on the real implementation.

Decoration is an alternative way of sub classing to extend the functionality of existing classes. Here is some scenario where we should use sub classing or decorator.

1) Sub classing mainly used in the case of extend the functionality of similar
group of classes which wants to retain the old functionality as well as new
in the sub classes
and all the instances of the sub classes share the same functionality. If we
make the changes of child classes and then it will reflect all the instaces
of child classes.Such as
a hierarchy relation ship, similar group of classes.

Parent->Child->GrandSon.

Car->Maruti 800->Maruti 100( will have the feature of Maruti 800 as well as New)

2) Decorator pattern is used to decorate the existing classes without changing the old behavior.Such as a class circle have plain border but we need to decorate it with red border,after some time some user wants circle with yellow color and some user wants circle with green border and some user wants red and yellow border circle and some user wants red and green border circle etc,for this it is the perfect pattern as it will reduces no of combination classes.Below is the example.

Icircle cir=new RedDecorator(new circle()) decorating the circle with red color

Icircle cir=new YellowDecorator(new circle()) decorating the circle with Yellow color

Icircle cir=new RedDecorator(new YellowDecorator(new circle())) decorating the

circle with red and Yellow, here we do not need to create RedAndYellow class decorator. same way we can decorate the circle with other set of combination without creating new set of combination classes.

In this way it reduces the no of combination classes.

Here is the useful link for decorator pattern

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

私藏温柔 2024-10-21 23:50:02

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

Flexibility, that's the reason IMO.

浅浅淡淡 2024-10-21 23:50:01

GoF 的一个例子:

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

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

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

An example from GoF:

Suppose you have a TextView class. Then in someplace you want a scrolled text view, so you subclass TextView and create ScrolledTextView class. And in some other place, you want a border around text view. So you subclass again and create BorderedTextView. Well, now in someplace you want border and scroll both. None of the previous two subclasses have both capabilities. So you need to create a 3rd one. When creating a ScrolledBorderedTextView you are actually duplicating the effort. You don't need this class if you have any way to compose the capability of the previous two. Well, things can go worse and these may lead to an unnecessary class explosion.

Basically, by using the decorator pattern you can add any number of additional responsibility to object at RUNTIME which you can not achieve by subclassing without potentially damaging your code structure or adding many duplicate combinations for subclasses.

But one thing, Design patterns are not something that you must use.
Whether a pattern is needed or not is dependent on your particular problem, you want to maintain the code for a long time or not, whether you want to extend or not and on many other factors like these.
And there is no pattern that is useful in all cases.
A pattern (decorator or anything else) suitable for a situation may not be a good choice for another situation.

时光倒影 2024-10-21 23:50:01

来自 维基百科上的装饰器模式

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

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

来自同一篇文章:

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

from Decorator pattern at wikipedia

The decorator pattern can be used to
make it possible to extend (decorate)
the functionality of a certain object
at runtime.

The whole point of decorator pattern is to dynamically add additional behaviour/functionality, which is of course not possible at design time.

from the same article:

The decorator pattern is an
alternative to subclassing.
Subclassing adds behavior at compile
time
, and the change affects all
instances of the original class;
decorating can provide new behavior at
runtime for individual objects
.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文