何时以及如何应用策略模式而不是装饰模式?

San*_*box 9 design-patterns strategy-pattern

我正在学习设计模式并试图遵循Go4书.在页面:179,在装饰模式章节中,有一行说

"通过将策略的数量从一个扩展到一个开放式列表,我们可以递归地实现与嵌套装饰器相同的效果."

我没有得到这个声明.

策略侧重于拥有独立的算法,这些算法可以动态设置,并且不太了解它们所设置的客户端.

而装饰者并不完全独立于他们装饰的客户.实际上,它们与它们装饰的对象具有相同的超类型.

我在这里错过了一点吗?

Don*_*oby 14

我将引用一些我认为需要的上下文来理解这一点.

在Component类本质上是重量级的情况下,策略是更好的选择,从而使得Decorator模式的成本太高而无法应用.在策略模式中,组件将其一些行为转发给单独的策略对象.策略模式允许我们通过替换策略对象来更改或扩展组件的功能.

例如,我们可以通过让组件将边框绘制延迟到单独的Border对象来支持不同的边框样式.Border对象是一个策略对象,它封装了边框绘制策略.通过将策略的数量从一个扩展到一个开放式列表,我们可以递归地实现与嵌套装饰器相同的效果.

所有这一切都说两种模式都可以用来为你的基础组件添加行为,而使用Decorator,添加多种行为,你可以嵌套装饰器,而使用策略,你需要使用多种策略.

你是对的,策略通常比装饰器更独立于主要组件,但是他们可能知道组件.并且为了使用策略模式,主要组件意识到策略的存在,而Decorator则不需要这些策略.


Nat*_*man 6

要使用他们的示例,您可能有一个窗口类可以滚动和/或以各种方式绘制边框(或根本不绘制).如果你要使用继承来覆盖所有这些功能,那么每个可行的功能组合都需要一个子类(没有边框没有滚动,没有滚动的边框,没有边框的滚动,边框和滚动等)​​.这是一个不灵活的维护噩梦,因为您添加了更多功能,因为类的数量激增.

他们在这里提出的要点是你可以使用策略模式或装饰模式来更好地解决这个问题.你可以有一个Window类,它封装了一个滚动策略对象和一个边框策略对象.或者您可以将您的Window对象包装在边框装饰器中并将其包装在滚动装饰器中.

但是你的理解是完全正确的; 这是两种不同的设计模式,具有不同的特性,导致不同的应用.使用Decorator,Component不知道正在添加功能的代理程序......因此您最终会围绕现有的组件类构建.使用策略,这是另一种方式,因为组件正在使用(并因此知道)代理来执行各种任务 - 这些代理通常不了解其管理组件.