策略模式如何工作?

How does the Strategy Pattern work?

它是如何工作的,用途是什么,何时应使用它?


让我们以简单的方式来说明策略模式:

您有一个带有方法run()的类Car(),因此您可以在伪语言中以这种方式使用它:

1
2
mycar = new Car()
mycar.run()

现在,您可能想在程序执行时即时更改run()行为。例如,您可能想模拟电动机故障或在视频游戏中使用"升压"按钮。

有几种方法可以进行此模拟:使用条件语句和标志变量是一种方法。策略模式是另一种:将run()方法的行为委托给另一个类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Class Car()
{
    this.motor = new Motor(this)

    // passing"this" is important for the motor so it knows what it is running

    method run()
    {
        this.motor.run()
    }

    method changeMotor(motor)
    {
        this.motor = motor
    }

}

如果要更改汽车的性能,则只需更改电动机即可。 (在程序中比在现实生活中容易,对吗?;-))

如果您有很多复杂的状态,这将非常有用:您可以更轻松地进行更改和维护。


问题

策略模式用于解决可能(或预见到可能)通过不同策略实施或解决的问题,并且这些问题具有明确定义的界面。每种策略本身都是完全有效的,其中某些策略在某些情况下更可取,从而允许应用程序在运行时在它们之间进行切换。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
namespace StrategyPatterns
{
  // Interface definition for a Sort algorithm
  public interface ISort
  {
    void Sort(List<string> list)
  }

  // QuickSort implementation
  public class CQuickSorter : ISort
  {
    void Sort(List<string> list)
    {
      // Here will be the actual implementation
    }
  }

  // BubbleSort implementation
  public class CBubbleSort : ISort
  {
    void Sort(List<string> list)
    {
      // The actual implementation of the sort
    }
  }

  // MergeSort implementation
  public class CMergeSort : ISort
  {
    void Sort(List<string> list)
    {
      // Again the real implementation comes here
    }
  }

  public class Context
  {
    private ISort sorter;

    public Context(ISort sorter)
    {
      // We pass to the context the strategy to use
      this.sorter = sorter;
    }

    public ISort Sorter
    {
      get{return sorter;)
    }
  }

  public class MainClass
  {
    static void Main()
    {
       List<string> myList = new List<string>();

       myList.Add("Hello world");
       myList.Add("Another item");
       myList.Add("Item item");

       Context cn = new Context(new CQuickSorter());
       // Sort using the QuickSort strategy
       cn.Sorter.Sort(myList);
       myList.Add("This one goes for the mergesort");
       cn = new Context(new CMergeSort());
       // Sort using the merge sort strategy
       cn.Sorter.Sort(myList);
    }
  }
}


  • 什么是策略?战略是旨在实现特定目标的行动计划;
  • "定义一系列算法,封装每个算法,并使它们可互换。策略使算法独立于使用该算法的客户端而变化。"(四人制);
  • 指定一组类,每个类代表一种潜在的行为。在这些类之间切换会更改应用程序的行为。 (该策略);
  • 可以在运行时(使用多态)或设计时进行选择。
  • 在接口中捕获抽象,将实现细节埋在派生类中;

enter image description here

  • 该策略的替代方法是通过使用条件逻辑来更改应用程序行为。 (坏);
  • 使用此模式使添加或删除特定行为变得更加容易,而无需重新编码和重新测试应用程序的全部或部分。

  • 良好的用途:

    • 当我们有一组相似的算法时,需要在应用程序的不同部分之间进行切换。使用策略模式可以避免故障并简化维护;
    • 当我们想为超类添加不一定对每个子类都有意义的新方法时。代替以传统方式使用接口,而是添加新方法,我们使用实例变量,该实例变量是新Functionality接口的子类。这称为组合:类不是通过继承来继承功能,而是由具有适当功能的对象组成;

密切相关的模式是"委托"模式。在这两种情况下,某些工作都会传递给其他组件。如果我正确理解,则这些模式之间的区别是这样(如果我错了,请纠正我):

  • 在Delegate模式中,委托是通过封闭(委托)类实例化的;这允许通过组合而不是继承来重用代码。封闭的类可能知道委托人的具体类型,例如如果它本身调用其构造函数(而不是使用工厂)。

  • 在策略模式中,执行策略的组件是通过其构造函数或设置器(根据您的信仰)提供给封闭(使用)组件的依赖项。使用组件完全不知道正在使用什么策略。该策略始终通过接口调用。

有人知道其他区别吗?


直接来自Strategy Pattern Wikipedia文章:

The strategy pattern is useful for situations where it is necessary to dynamically swap the algorithms used in an application. The strategy pattern is intended to provide a means to define a family of algorithms, encapsulate each one as an object, and make them interchangeable. The strategy pattern lets the algorithms vary independently from clients that use them.


要添加到已经精妙的答案中:策略模式与将一个(或多个)函数传递给另一个函数有很大的相似性。在该策略中,这是通过将所述函数包装在对象中,然后传递对象来完成的。某些语言可以直接传递函数,因此它们根本不需要模式。但是其他语言不能传递函数,但是可以传递对象。该模式将适用。

尤其是在类似Java的语言中,您会发现该语言的类型库非常小,并且扩展它的唯一方法是创建对象。因此,大多数解决问题的方法都是提出一种模式。一种组合对象以实现特定目标的方法。动物园类型丰富的语言通常具有解决问题的简单方法-但是类型丰富也意味着您必须花费更多的时间来学习类型系统。具有动态打字规则的语言通常也可以轻松地解决问题。


推荐阅读

    linux执行多次命令?

    linux执行多次命令?,系统,信息,标准,工作,情况,命令,周期性,服务,代码,时间,l

    linux并行化执行命令?

    linux并行化执行命令?,系统,工具,信息,命令,名称,网络,管理,首页,服务,暂停,L

    如何执行linux命令?

    如何执行linux命令?,单位,系统,网络,信息,权威,命令,文件,音乐,目录,选项,mv

    linux打断执行的命令?

    linux打断执行的命令?,系统,状态,网站,标准,通用,客服,人员,名字,网络,暂停,L

    linux命令没执行完?

    linux命令没执行完?,系统,设备,工具,情况,密码,状态,电脑,管理,材料,服务,Lin

    shell中执行linux命令?

    shell中执行linux命令?,系统,名称,环境,管理,工作,代码,技术,软件,经理,基础

    linux打印命令执行?

    linux打印命令执行?,信息,系统,工具,服务,命令,发行,基础,位置,设备,时间,怎

    linux执行两次命令?

    linux执行两次命令?,系统,信息,连续,名称,命令,初级,首页,工具,管理,终端,lin

    linux命令执行安装?

    linux命令执行安装?,软件,系统,管理,网站,官网,市场,中心,最新,灵活,工作,如

    linux执行一条新命令?

    linux执行一条新命令?,系统,工作,命令,管理,网络,服务,信息,目录,路径,脚本,L

    监控linux执行命令?

    监控linux执行命令?,系统,情况,数据,实时,网络,信息,状态,时间,设备,命令,如

    linux命令卡死不执行?

    linux命令卡死不执行?,系统,设备,数据,密码,工具,情况,软件,环境,分析,命令,l

    linux执行c程序命令?

    linux执行c程序命令?,系统,工作,工具,信息,代码,命令,文件,保险,管理,环境,li

    linux命令执行中断?

    linux命令执行中断?,设备,系统,网络,工具,工作,通用,状态,名字,流程,进程,lin

    执行linux脚本命令行?

    执行linux脚本命令行?,工具,位置,地方,环境,数据,状态,暂停,增长,系统,基础,

    linux远端执行命令?

    linux远端执行命令?,系统,状态,软件,名称,密码,暂停,网络,环境,认证,在线,如

    linux命令行执行成功?

    linux命令行执行成功?,系统,信息,状态,服务,管理,百度,设计,灵活,代码,命令,L

    安卓执行linux命令行?

    安卓执行linux命令行?,系统,设备,基础,发展,标准,情况,信息,电话,号码,工具,

    c执行在linux命令?

    c执行在linux命令?,系统,环境,保险,工具,代码,命令,程序,文件,终端,语言,如何

    linux执行中退出命令?

    linux执行中退出命令?,档案,状态,命令,分析,数据,电脑,实时,系统,工具,编辑,l