策略模式V / S装饰模式

时间:2014-10-17 10:19:07

标签: design-patterns decorator strategy-pattern

我刚遇到两种模式。

  1. 策略模式

  2. 装饰员

  3.   

    策略模式: -

         

    策略模式提供了几种可用于执行的算法   特定的操作或任务。

         

    装饰图案: -

         

    装饰器模式为组件添加了一些功能。

    事实上,我发现策略模式和装饰器模式也可以互换使用。

    这是链接: - When and How Strategy pattern can be applied instead of decorator pattern?

    策略模式和装饰模式有什么区别?

    何时应使用策略模式以及何时应使用Decorator模式?

    用同一个例子解释两者之间的区别。

7 个答案:

答案 0 :(得分:84)

策略模式允许您更改运行时使用的内容的实现。

装饰器模式允许您在运行时使用其他功能扩充(或添加)现有功能。

关键区别在于更改 vs augment

在与其链接的一个问题中,还指出,使用策略模式,消费者意识到存在不同的选项,而使用装饰器模式,消费者不会意识到其他功能。

作为一个例子,假设您正在编写一些内容来对元素集合进行排序。因此,您编写了一个界面ISortingStrategy,然后您可以实施几种不同的排序策略BubbleSortStrategyQuickSortStrategyRadixSortStrategy,然后您的应用程序根据现有列表的某些标准选择用于对列表进行排序的最合适的策略。因此,例如,如果列表中包含的项目少于10个,我们将使用RadixSortStrategy,如果自上次排序后列表中添加的项目少于10个,我们将使用BubbleSortStrategy,否则我们将使用{{1} }}

我们正在改变运行时的排序类型(基于一些额外信息更有效率。)这是策略模式。

现在想象有人要求我们提供每个排序算法用于执行实际排序的频率以及限制排序给管理员用户的日志。我们可以通过创建一个增强任何 QuickSortStrategy的装饰器来添加这两个功能。我们可以创建一个装饰器来记录它用于排序的东西和装饰排序策略的类型。我们可以添加另一个装饰器,在调用装饰排序策略之前检查当前用户是否是管理员。

这里我们使用装饰器为任何排序策略添加新功能,但是没有交换核心排序功能(我们使用不同的策略来改变它)

以下是装饰器外观的示例:

ISortingStrategy

答案 1 :(得分:9)

Strategy_pattern

  1. 定义一系列算法,
  2. 封装每个算法,
  3. 使算法在该系列中可互换。
  4. 在运行时必须动态更改算法时使用策略模式。

    Decorator

    装饰器 模式在运行时动态更改对象的功能,而不会影响对象的现有功能。

    何时使用:

    1. 动态添加其他功能/职责
    2. 动态删除功能/职责
    3. 避免过多的子类化以增加额外的责任。
    4. <强>缺点:

      1. 过度使用Open Closed原则(Open for extension和Closed for modification)。在代码最不可能更改的地方谨慎使用此功能。
      2. 太多小班,会增加维护费用。
      3. 关键区别:

        策略可让您更改对象的内容。装饰器可让你改变皮肤。

        几个有用的帖子:

        When to Use the Decorator Pattern?

        Real World Example of the Strategy Pattern

        源代码制作

        strategy

答案 2 :(得分:5)

策略是模式用于“封装什么变化”。它允许您定义可在运行时互换的算法。例如(取自Head First Design Patterns的例子):

假设你有一个鸭子模拟器。你想让你的鸭子物体飞翔。你可以使用继承,但它很快就会变得混乱。有些鸭子不会飞(例如橡皮鸭)。这样做的方法是将所谓的变化(即飞行行为)封装到其自己的类中,例如实现IFlybehaviour。然后,您可以使用合成而不是继承,并将IFlybehaviour注入到鸭子对象中。然后,您还可以使用一种方法来设置此飞行行为,以便可以在运行时更改飞行行为。这基本上就是战略模式。

装饰器模式用于在运行时向对象添加功能。它允许您将对象包装在对象中。装饰器必须与它们装饰的对象具有相同的超类型。这允许您在“最外层包装器”上调用方法,然后您可以通过装饰器层向下调用相同的方法。它基本上比子类化更灵活。

您选择哪些取决于您要解决的问题。您是否希望拥有一系列可在运行时互换的algorthims,或者您是否希望在运行时动态地向对象添加更多功能?

“头脑第一设计模式”一书很好地解释了这一点(可能比我好得多)IMO所以如果你有机会就值得一读。

祝你好运。

答案 3 :(得分:1)

归结为:使用策略选择一项核心功能。使用Decorator添加额外的功能。策略是我们正在制作的蛋糕,而Decorator是我们添加的所有装饰。

答案 4 :(得分:0)

Decorator是为类的实例添加额外的功能,因此它是在运行时动态实现的。它是一种行为扩展模式。由于Subclassing重新打破的实际条件。 策略是不同策略对象共享相同抽象函数的模式,具体上下文对象可以在运行时与族集的具体策略对象配置。 作为MVC,控制器是策略角色的一种情况,视图限制输出数据结构,而控制器在运行时将不同,这会动态地改变视图的输出数据。

答案 5 :(得分:0)

策略正在选择一种算法。

Collections.sort(list, comparator); // comparator is the strategy

装饰器在包装对象的同时保留了相同的类型。

in = new BufferedInputStream(in);

答案 6 :(得分:0)

我要说的是,策略模式允许您选择多种方式中的一种来执行某项操作,或者为多种操作选择多种实现方式,而装饰器模式允许您通过使用所需的对象(实际上是它的类和/或接口)功能及其实现(为了创建所需的对象,无论您想要哪个以及想要多少次)。

两者都是动态完成的,换句话说,是在运行时完成的。

策略模式示例

您正在读取文件夹的内容。它包含普通的 .txt .csv JSON 文件。从 IReader 接口调用某些方法 Read(),但是根据文件的类型,使用 Read()方法的适当实现。使用策略模式来决定执行哪种方法。

装饰图案示例

Read()方法的结果导出到某些 XML 文件中,但是根据结果, XML中的某些Header节点可以包含一个或多个节点,并且一个节点的内容可以不同。 Header可能包含或可能不包含Date节点,该节点可能具有以下几种日期格式之一;它可能包含或可能不包含ReadDuration节点,可以用毫秒,秒或分钟表示(带有附加的节点,表示使用哪个单位);它可能包含一个节点,也可能不包含一个代表读取的项目数量的节点,例如NumberOfItemsNumberOfRows或类似的东西。

因此,某些 XML Header节点示例包含:

  • Date节点,其中日期格式为YYYY-MM-DD,而ReadDuration节点表示读取文件花费了多少秒
  • Date节点,其日期格式为DD-MM-YYYY
  • Date节点,其格式为YYYY-MM-DD,ReadDuration节点表示读取文件和NumberOfRows节点花费了多少毫秒
  • ReadDuration节点,它表示读取文件和NumberOfRows节点花费了多少毫秒
  • ReadDuration节点,表示读取文件和NumberOfRows节点花费了几秒钟
  • Date节点,其格式为YYYY-MM-DD,ReadDuration节点,表示读取文件,NumberOfRows节点和NumberOfItems节点花费了多少毫秒。 / li>
  • 依此类推