【问题标题】:When and How Strategy pattern can be applied instead of decorator pattern?何时以及如何应用策略模式而不是装饰器模式?
【发布时间】:2011-05-20 06:28:44
【问题描述】:
我正在学习设计模式并尝试遵循 Go4 书籍。在第 179 页,在装饰器模式章节中,有一行写着
"..通过将策略的数量从一个扩展到一个
开放式列表,我们达到和嵌套装饰器一样的效果
递归。”
我不太明白这个说法。
策略侧重于拥有独立的算法,这些算法可以动态设置,并且不太了解它们所在的客户端。
而装饰者并不完全独立于他们所装饰的客户。实际上,它们与它们所装饰的对象具有相同的超类型。
我在这里漏掉了一点吗?
【问题讨论】:
标签:
design-patterns
strategy-pattern
【解决方案1】:
我将引用更多我认为有意义的上下文。
在组件类本质上是重量级的情况下,策略是更好的选择,从而使装饰器模式成本过高而无法应用。在策略模式中,组件将其一些行为转发给单独的策略对象。策略模式允许我们通过替换策略对象来改变或扩展组件的功能。
例如,我们可以通过让组件将边框绘制推迟到单独的 Border 对象来支持不同的边框样式。 Border 对象是一个封装了边框绘制策略的 Strategy 对象。通过将策略的数量从一个扩展到一个开放式列表,我们实现了与递归嵌套装饰器相同的效果。
这就是说,这两种模式都可以用来向你的基础组件添加行为,而对于装饰器,要添加多个行为,你可以嵌套装饰器,而对于策略,你需要使用多种策略。
你说得对,策略通常比装饰器更独立于主组件,但他们有可能知道组件。为了使用策略模式,主要组件知道策略的存在,而装饰器不需要。
【解决方案2】:
要使用他们的示例,您可能有一个可以滚动的窗口类和/或以各种方式绘制其边框(或根本不绘制)。如果您要使用继承来涵盖所有这些功能,那么您需要一个子类来处理每种可行的功能组合(无边框无滚动、无边框无滚动、无边框滚动、边框和滚动等)。当您添加更多功能时,这是一个不灵活的维护噩梦,因为类的数量呈爆炸式增长。
他们在这里提出的主要观点是,您可以使用策略模式或装饰器模式来更好地解决这个问题。您可以有一个封装滚动策略对象和边框策略对象的 Window 类。或者,您可以使用 Window 对象,将其包装在边框装饰器中,然后将其包装在滚动装饰器中。
但是您的理解完全正确;这是两种不同的设计模式,具有不同的特点,导致不同的应用。使用装饰器,组件不知道正在添加功能的代理......因此您最终倾向于围绕现有的组件类进行构建。对于 Strategy,情况正好相反,因为组件使用(因此知道)代理来执行各种任务 - 这些代理通常不知道它们的管理组件。
【解决方案3】:
当您想对某事使用多种方法时,请使用策略模式。当您想创建某些东西可能会或可能不会用于更改对象/组件/任何东西的东西时,那么您应该使用装饰器。换句话说,也可以说装饰器可能会为对象添加功能(装饰),而策略可能会交换功能。
【解决方案4】:
区别在于,在策略模式中,一个策略对象可以一次用于向上下文提供信息。使用 Decorator,您可以将策略堆叠在一起,从而获得他们所说的“开放式”数字。
【解决方案5】:
当对象的身份对您很重要时,可以应用策略模式。无论应用了多少策略,对象标识仍然存在,但对于装饰器模式
对象相互封装,原始身份将在转换中丢失
装饰器模式改变对象的皮肤
策略模式改变了对象的内涵。