# 策略模式


## ***组件协作模式***

1. ***什么是组件协作模式***
   - *现代软件专业分工之后的第一个结果就是 **框架与应用程序的划分***
   - ***组件协作*** *模式通过晚绑定，来实现框架和应用之间的松耦合，是二者之间协作时常用的模式*
2. ***典型模式***
   - *Template Method*
   - *Observer / Event*
   - *Strategy*

## ***使用策略模式的动机***

1. *在软件构建的过程中，某些对象使用的算法可能多种多样的，经常改变，如果将这种算法都编码到对象中，将会使对象变得异常复杂，而且有时候支持不使用的算法也是一个性能负担*
2. *如何在运行时根据需要透明的更改对象的算法? 将算法与对象本身解藕 从而避免上述问题*

## ***静态代码***

1. ***场景***
   
   - *每个国家税不同 所以要根据税去计算*

2. ***演示代码及代码思路***
   
   - *这里的思路 就是 直接用一个枚举 记录各个国家的税 然后 根据不同的税 进行 if else if 计算，这里带来的需求变化 也是麻烦的 如果要加一个法国的税 就得新加else if 巨麻烦 这个就违反了 开放封闭 面向对象设计原则 支持扩展 拒绝更改，这样代码就会变成静态思路 这时候 我们扩展一下思路 加个"时间轴" 变成动态的*
     
     ```cpp
     enum TaxBase {
       CN_Tax,
       US_Tax,
       DE_Tax
     };
     
     class SalesOrder {
       TaxBase tax;
     public:
       double CalculateTax() {
         if (tax == CN_Tax) {
           // CN....
         }
         else if (tax == US_Tax) {
           // US...
         }
         else if (tax == DE_Tax) {
           // DE...
         }
         //...
       }
     }
     ```

## ***动态代码***

1. ***场景***
   - *每个国家税不同 所以要根据税去计算*
2. ***演示代码及思路***
   - *在下述代码中，如果我们要增加一个法国的税，只需要写一个法国的子类，这样就是扩展，而不是更改了枚举，还有增加了if else*
   - *当然你其实会有这样的疑问，在静态代码的思路，if else 的代码不是也没有动，就只是加了一个 else if 这不也是复用扩展嘛*
   - *这肯定不叫复用，复用是编译级别，编译之后，部署之后，原封不动，而且你想的太美好，在大量的else中，很有可能也要改变前面的思路，从而引发bug*

## ***模式定义***

1. *定义一系列算法 把他们一个个封装起来 并且使他们可互相替换(变化)*
2. *该算法使得算法可独立于使用他的客户程序(稳定)而变化(扩展，子类化)*

## ***类图***

![策略模式的类图](https://raw.githubusercontent.com/vlicecream/cloudImage/main/data/imagesimage-20220525232619305.png)

## ***要点总结***

1. *Strategy及其子类为组件提供了一系列可重用的算法 从而可以使得类型在运行时方便的根据需要在各个算法之间进行切换*
2. *Strategy模式提供了在条件判断语句以外的另一种选择 消除条件判断语句 就是在解耦合 含有许多条件判断语句的代码通常都需要策略模式*
3. *如果Strategy对象没有实例变量， 那么各个上下文可以共享一个Strategy对象 从而节省对象开销*
4. *额外的解释*
   - *运行时 这个词 就是代码中多态调用的时候*
   - *其实 if else if 和 switch case 就是 分解 这个思路，我们将各种具体的计算税的算法抽象成了算法类，这个就是抽象的概念*
   - ***不是所有的 if else策略模式就适用 在 if else绝对不变的情况下就可以用 if else*** *比如一周有7天的情况下 不能多出第八天 所以就可以用if else*

