c++ 设计模式4 (Strategy)

3.2 Strategy (策略模式)

动机:在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂,而且有时候支持不使用或不常使用的算法也是一个性能负担。

如何在运行时根据需要透明地改变对象的算法?将算法和对象本身解耦,从而避免上述问题?

 

代码示例:

如果使用第一种方法,需要更改枚举类型和if else语句(第6行和24行),违背了开放封闭原则(对扩展开发,对修改封闭);

采用第二种方法(策略模式),定义税法基类,对不同国家税法定义不同子类,override Calculate方法。59行,多态调用。

假设出现变化:扩展32 - 39行,SalesOrder不变(复用性,遵循开放封闭原则)。

补:面向对象提到的复用性,指的是编译单位(二进制单位)的复用性,不是粘贴代码的复用性

复制代码
 1 // strategy1.cpp
 2 enum TaxBase {
 3     CN_Tax,
 4     US_Tax,
 5     DE_Tax,
 6     FR_Tax       //更改
 7 };
 8 
 9 class SalesOrder{
10     TaxBase tax;
11 public:
12     double CalculateTax(){
13         //...
14         
15         if (tax == CN_Tax){
16             //CN***********
17         }
18         else if (tax == US_Tax){
19             //US***********
20         }
21         else if (tax == DE_Tax){
22             //DE***********
23         }
24         else if (tax == FR_Tax){  //更改
25             //...
26         }
27 
28         //....
29      }
30   
复制代码
复制代码
 1 //Strategy.cpp
 2 class TaxStrategy{
 3 public:
 4     virtual double Calculate(const Context& context)=0;
 5     virtual ~TaxStrategy(){}
 6 };
 7 
 8 
 9 class CNTax : public TaxStrategy{
10 public:
11     virtual double Calculate(const Context& context){
12         //***********
13     }
14 };
15 
16 class USTax : public TaxStrategy{
17 public:
18     virtual double Calculate(const Context& context){
19         //***********
20     }
21 };
22 
23 class DETax : public TaxStrategy{
24 public:
25     virtual double Calculate(const Context& context){
26         //***********
27     }
28 };
29 
30 
31 
32 //扩展
33 //*********************************
34 class FRTax : public TaxStrategy{
35 public:
36     virtual double Calculate(const Context& context){
37         //.........
38     }
39 };
40 
41 
42 class SalesOrder{
43 private:
44     TaxStrategy* strategy;
45 
46 public:
47     SalesOrder(StrategyFactory* strategyFactory){
48         this->strategy = strategyFactory->NewStrategy();
49     }
50     ~SalesOrder(){
51         delete this->strategy;
52     }
53 
54     public double CalculateTax(){
55         //...
56         Context context();
57         
58         double val = 
59             strategy->Calculate(context); //多态调用
60         //...
61     }
62     
63 };
复制代码

定义: 定义一系列算法, 把它们一个个封装起来,并且使它们可以互相替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)。

 

类图:

要点总结:

Strategy及其子类为组件提供了一系列可重用的算法,从而可以得到类型在运行时方便地根据需要在各个算法之间进行切换。

Strtegy模式提供了用条件判断语句以外的另一种选择消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式。(除非if else语句绝对不变,如对一周七天判断等)

如果Strategy对象没有实例变量,那么各个上下午可以共享同一个Strategy对象,从而节省对象开销。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值