[设计模式] —— Strategy 策略模式

Strategy 策略模式

组件协作模式通过晚绑定,来实现框架与应用程序之间的松耦合。是框架和引用程序协作常用的。

动机

某些对象使用的算法可能多种多样,经常改变,将这些算法都编码到对象中,使对象变得异常复杂,而且有时支持不适用的算法也是一种性能负担。想要在运行时根据需要透明地更改对象的算法,就要将算法与对象本身解耦,从而避免上述问题。

定义

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

示例代码
enum TaxBase {
    CN_Tax,
    USA_Tax
};

class SalesOrder {
private:
 TaxBase tax;
public:
 double CalculateTax() {
     // ...
     if (tax == CN_Tax) {
         // CN_...
     } else if (tax == USA_Tax) {
         // USA...
     }
 }
};

现有上面的示例代码,有一个 SalesOrder 类来计算税收,税现在有 CN_Tax 和 USA_Tax 类两种,用枚举表示,这里实现就根据 tax 的类型类做条件表达式的判读。 这样的代码还是在日常开发中蛮常见的,但是这样的代码有一个问题,就是当有需求变化时,我们即需要修改枚举类型,还要修改类的源代码。例如现在需要增加一个税收计算种类 FR_Tax,就需要将代码改成下面的形式:

enum TaxBase {
    CN_Tax,
    USA_Tax,
    FR_Tax // 新增代码
};

class SalesOrder {
private:
 TaxBase tax;

public:
 double CalculateTax() {
     // ...
     if (tax == CN_Tax) {
         // CN_...
     } else if (tax == USA_Tax) {
         // USA...
     } else if (tax == FR_Tax) { // 新增代码
        // FR...
     }
 }
};

其实上面这种方式就违背了开闭原则,即对修改封闭,对扩展开放。这种情况下,使用策略模式就是由上面的定义,将类型一个个封装起来:

class TaxStrategy {
public:
 virtual double Caculate(const Context& context) = 0;
 virtual ~TaxStrategy(){}
};

class CNTax : public TaxStrategy {
public:
 virtual double Caculate(const Context& context) {
     // ...
 }
};

class USATax : public TaxStrategy {
public:
   virtual double Caculate(const Context& context) {
     // ...
 }
}

class SalesOrder {
private:
 TaxStrategy* strategy; // 使用指针实现多态

public:

  SalesOrder(strategyFactory* strategyFactory) { // 工厂方法来生成对应子类
      this->strategy = strategyFactory->NewStrategy();
  }

  ~SalesOrder() {
      delete this->strategy;
  }

  double CalculateTax() {
      // ...
      Context context;
      double val = strategy->Caculate(context); // 多态调用
  }
};

这个时候我们如果再想扩展 FR_Tax 类型则可以在上述代码的基础上,增加一个 TaxStrategy 的 FRTax 的子类(以及相应的工厂方法的子类)即可,无须再修改 SalesOrder 类的代码了。这里使用了工厂方法来生成子类对象,这部分不是本模式的重点,后面会详细介绍工厂方法。

class FRTax : public TaxStrategy {
public:
   virtual double Caculate(const Context& context) {
     // ...
 }
}

上述的方式就是 Strategy 策略模式的内容了。

结构图
总结
  • Strategy 策略模式及其子类为组件提供了一系列可重用的算法,从而是的类型在运行时方便地根据需要在各算法间进行切换。
  • 提供了条件判断语句之外的另一种选择。上面的例子可以看出,消除条件判断表达式就是在解耦合,含多个条件判断语句的代码通常都需要 stategy 模式。
  • 如果 Stategy 对象没有实例变量,上下文可以共享同一个对象,能节省对象开销。

其他设计模式汇总:
[设计模式] —— 设计模式的介绍及分类

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值