设计模式解析(五)——几种设计模式之Strategy

《设计模式》一书中对Strategy模式的意图叙述如下:

定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换,Strategy模式使算法可独立于使用它的客户而变化。

strategy模式以下列原则为基础:

1.对象都具有职责
2.这些职责不同的具体实现是通过多态的使用完成的
3.概念上相同的算法具有多个不同的实现,需要进行管理
 
  Strategy模式:关键特征

意图

可以根据所处的上下文,使用不同的业务规划或算法

问题

对所需算的选择取决于发出请求的客户或者要处理的数据。如果只有一些不会变化的算法,就不需要Strategy模式。

解决方案

将对算法的选择和算法的实现相分离。允许根据上下文进行选择。

参与者与协作者

  • strategy指定了如何使用不同的算法。
  • 各ConcreteStrategy实现了这些不同的算法。
  • Context通过类型为Strategy的引用使用具体的ConcreteStrategy。Strategy与Context相互作用以实现所选的算(有时候Strategy必须查询Context)。Context将来自Client的请求转发给Strategy。

效果

  • Strategy模式定义了一系列的算法。
  • 可以不适用switch语句或条件语句。
  • 必须以相同的方式调用所有的算法(它们必须拥有相同的接口)。个ConcreteStrategy与Context之间的相互作用可能需要在Context中加入获取状态的方法。

实现

让使用算法的类(Context)包含一个抽象类(Strategy),该抽象类有一个抽象方法指定如何调用算法。每个派生类按照需要实现算法。注意:在原型Strategy模式中,选择所用具有实现的职责由Client对象承担,并转给Strategy模式的Context对象。

Stategy模式的通用结构图

Strategy

Strategy模式会带来爆炸性增长问题的解决方法

C++

可以用Strategy抽象类头文件包含所有ConcreteStrategy类的头文件。同时用|Strategy抽象类的cpp文件包含各ConcreteStrategy的代码。

Java

可以在Strategy抽象类内使用内部类包含所有的ConcreteStrategy。

但是如果无法控制所有的Strategy对象,也就是说如果有其它程序员需要实现自己的算法,就不要这么做。

代码示例:

TaxController.h
 1 //TaxController.h
 2 #pragma once
 3 #include "CalcTax.h"
 4 
 5 class TaskController
 6 {
 7 public:
 8     TaskController(void);
 9     void process();
10     CalcTax *getTaxRulesForCountry();
11 public:
12     ~TaskController(void);
13 };
14 TaxController.cpp
15 #include "TaskController.h"
16 #include "SalesOrder.h"
17 #include "CalcTax.h"
18 #include "USTax.h"
19 
20 TaskController::TaskController(void)
21 {
22 }
23 
24 TaskController::~TaskController(void)
25 {
26 }
27 
28 void TaskController::process ()
29 {
30     // this code is an emulation of a 
31     // processing task controller
32     // . . .
33     // figure out which country you are in
34     CalcTax *myTax;
35     myTax= getTaxRulesForCountry();
36     SalesOrder *mySO= new SalesOrder();
37     mySO->process( myTax);
38 }
39 
40 CalcTax *TaskController::getTaxRulesForCountry() 
41 {
42     // In real life, get the tax rules based on
43     // country you are in.  You may have the
44     // logic here or you may have it in a
45     // configuration file
46     // Here, just return a USTax so this 
47     // will compile.
48     return new USTax;
49 }
SalesOrder.h
 1 //SalesOrder.h
 2 #pragma once
 3 #include "CalcTax.h"
 4 
 5 class SalesOrder
 6 {
 7 public:
 8     SalesOrder(void);
 9     void process (CalcTax *TaxToUse);
10 public:
11     ~SalesOrder(void);
12 };
13 SalesOrder.cpp
14 #include "SalesOrder.h"
15 
16 SalesOrder::SalesOrder(void)
17 {
18 }
19 
20 SalesOrder::~SalesOrder(void)
21 {
22 }
23 
24 void SalesOrder::process (CalcTax *taxToUse)
25 {
26     long itemNumber= 0;
27     double price= 0;
28 
29     // given the tax object to use
30 
31     // . . .
32 
33     // calculate tax
34     double tax= taxToUse->taxAmount( itemNumber, price);
35 }
CalcTax.h
 1 //CalcTax.h
 2 #pragma once
 3 
 4 class CalcTax
 5 {
 6 public:
 7     CalcTax(void);
 8     double virtual taxAmount( long, double)= 0;
 9 public:
10     ~CalcTax(void);
11 };
12 CalcTax.cpp
13 #include "CalcTax.h"
14 
15 CalcTax::CalcTax(void)
16 {
17 }
18 
19 CalcTax::~CalcTax(void)
20 {
21 }
CanTax.h
 1 //CanTax.h
 2 #pragma once
 3 #include "calctax.h"
 4 
 5 class CanTax :
 6     public CalcTax
 7 {
 8 public:
 9     CanTax(void);
10     double taxAmount( long, double);
11 public:
12     ~CanTax(void);
13 };
14 CanTax.cpp
15 #include "CanTax.h"
16 
17 CanTax::CanTax(void)
18 {
19 }
20 
21 CanTax::~CanTax(void)
22 {
23 }
24 
25 double CanTax::taxAmount (long itemSold, double price) 
26 {
27     // in real life, figure out tax according to
28     // the rules in Canada and return it
29     // here, return 0 so this will compile
30     return 0.0;
31 }
USTax.h
 1 //USTax.h
 2 #pragma once
 3 #include "calctax.h"
 4 
 5 class USTax :
 6     public CalcTax
 7 {
 8 public:
 9     USTax(void);
10     double taxAmount( long, double);
11 
12 public:
13     ~USTax(void);
14 };
15 USTax.cpp
16 #include "USTax.h"
17 
18 USTax::USTax(void)
19 {
20 }
21 
22 USTax::~USTax(void)
23 {
24 }
25 
26 double USTax::taxAmount (long itemSold, double price) 
27 {
28     // in real life, figure out tax according to
29     // the rules in the US and return it
30     // here, return 0 so this will compile
31     return 0.0;
32 }
原文地址:https://www.cnblogs.com/sirocco/p/2956319.html