前言
本文中所有设计模式Github代码
其中本文策略模式 相关代码在StrategyPattern.h
文件中
一、策略模式基础
1. 策略模式的提出
在代码构建过程中,某些对象的算法可能有多种实现 (例如不同的排序算法、查找算法等),我们可以根据环境或者条件的不同选择不同的算法来完成任务。
如果将这些算法都封装到对象中 ,将会使对象变得很复杂,有时候支持不需要的算法也是一种负担 。
那么如何在运行时根据环境或者条件的不同选择不同的算法 来完成任务?
2.
策略模式的设计思想&&代码实现(C++)
2.1 策略模式使用场景示例
假设我们需要实现一个不同国家的税率计算算法 ,我们需要面对不同国家具有不同税率的问题
2.2
未使用策略模式的代码实现思路
当我们没有采用策略模式时,我们会在一个类 中提供不同国家的税率计算算法 ,然后在main程序中实现不同国家的税率计算算法 的调用来实现具体功能
在这种情况下,我们可能会想到通过枚举方法来代表不同的国家,然后在类中通过if-else语句来判断不同国家的税率计算算法
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 #include <iostream> using namespace std;enum TexType { CN_TAX, US_TAX, JP_TAX }; class SalesOrder { TexType type; public : double CalculateTax () { if (type == CN_TAX) { return 0.1 ; } else if (type == US_TAX) { return 0.2 ; } else if (type == JP_TAX) { return 0.3 ; } } };
但是很多情况下,业务需求变化是很快的,我们可能随时需要增加对新国家的税率计算算法,这样的话,我们就需要修改SalesOrder
类,也要改变枚举值,这样的话,我们就违反了开闭原则 ,所以我们需要使用策略模式来解决这个问题
策略模式通常还需要结合工厂模式 来使用,这样可以更好的解耦
2.3 使用策略模式的代码实现思路
当我们采用策略模式时,我们会在一个类 中提供一个抽象的策略类 ,然后在不同国家的税率计算算法 中继承这个抽象的策略类,然后在main程序中实现不同国家的税率计算算法 的调用来实现具体功能
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 #include <iostream> using namespace std;class TaxStrategy { public : virtual double Calculate () = 0 ; virtual ~TaxStrategy (){}; }; class CNTax : public TaxStrategy{ public : double Calculate () { return 0.1 ; } }; class USTax : public TaxStrategy{ public : double Calculate () { return 0.2 ; } }; class JPTax : public TaxStrategy{ public : double Calculate () { return 0.3 ; } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class SalesOrder { private : TaxStrategy* strategy; public : SalesOrder (TaxStrategy* strategy) { this ->strategy = strategy; } double CalculateTax () { return strategy->Calculate (); } ~SalesOrder () { delete strategy; } };
1 2 3 4 5 6 7 int main () { SalesOrder* order = new SalesOrder (new CNTax ()); cout << order->CalculateTax () << endl; delete order; return 0 ; }
在这种情况下,我们只需要添加一个继承自TaxStrategy
的新类,不需要修改SalesOrder
类,这样就符合了开闭原则
2.4 策略模式结合简单工厂抽象化
在上述代码中,我们可以看到new CNTax()
这里可以通过简单工厂方法将其抽象出来,这样可以更好的解耦
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class TaxStrategyFactory { public : static TaxStrategy* CreateTaxStrategy (TexType type) { switch (type) { case CN_TAX: return new CNTax (); case US_TAX: return new USTax (); case JP_TAX: return new JPTax (); default : return nullptr ; } } };
1 2 3 4 5 6 7 int main () { SalesOrder* order = new SalesOrder (TaxStrategyFactory::CreateTaxStrategy (CN_TAX)); cout << order->CalculateTax () << endl; delete order; return 0 ; }
这样我们就可以通过工厂模式将new CNTax()
这里抽象出来,这样可以更好的解耦,当然TaxStrategyFactory
的实现还可以进一步设计成抽象接口,将其改造为工厂方法模式,这里就不再赘述
二、总结
策略模式使得算法可以独立于客户程序 (稳定,如SalesOrder)而变化(不稳定、扩展,如CNTax、USTax、JPTax)
策略模式提供一系列可变的算法,客户程序在运行时只需要关心接口 ,不需要关心算法的内部实现细节
在代码中当出现if-else 语句 or
switch-case 语句时,一般就是需要使用策略模式 的时候了(使用策略模式抽象化代替if-else语句
or
switch-case语句)(只有在if-else是绝对不变的情况下可以不用将其优化为策略模式,比如一周只有7天,这种确定情况下就不需要优化为策略模式)