动机:在软件构建的过程当中,某些对象使用的算法可能多种多样,常常改变,若是将这些算法都编码到对象中,将会使对象变得异常复杂,增长与改变现有算法可能带来严重的逻辑问题;并且有时候支持不使用的算法也是一个性能上的负担(具体上体如今代码太长会使得其在保存的位置出现问题),所以将对象与算法解耦,避免上述问题才是本算法动机。
意图:定义一系列的算法,把它们一个个封装起来,而且使它们能够相互替换。本模式使得算法可独立于使用它的客户而改变。ios
示例代码:算法
#ifndef STRATEGY #define STRATEGY #include<iostream> using std::cout; using std::ends; using std::endl; class Tax_cal { public: Tax_cal(); ~Tax_cal(); virtual double get_tax(double source_money)const = 0; private: }; Tax_cal::Tax_cal() {} Tax_cal::~Tax_cal() {} class chinese_tax:public Tax_cal { public: chinese_tax(); ~chinese_tax(); double get_tax(double source_money) const { return source_money * 5.6/100 ; } }; chinese_tax::chinese_tax() {} chinese_tax::~chinese_tax() {} class Japanese:public Tax_cal { public: Japanese(); ~Japanese(); double get_tax(double source_money)const { return source_money * 17 / 100; } private: }; Japanese::Japanese() { } Japanese::~Japanese() { } class bank_calcu { public: bank_calcu(double); ~bank_calcu() {}; void Calculate(const Tax_cal*); private: double money; }; bank_calcu::bank_calcu(double money) :money(money) {}; void bank_calcu::Calculate(const Tax_cal* tax_demo) { cout << tax_demo->get_tax(money) << endl; } #endif // !STRATEGY
咱们定义了一个客户端的类bank_calcu用于计算不一样地方的税率,在成员函数Calculate()中计算税率,可是不一样的地方有不一样的税率,譬如说代码中的中国与日本(固然数据是瞎编的),传统的方法是在Calculate()内部写上一个if-else或者switch语句来进行区别,可是依旧存在问题:
一、用不到的代码块就应该被去除,不然影响执行效率;
二、违反了开闭原则(对增长开放,对修改封闭);
三、容易出错,如今的逻辑尚未那么复杂,判断逻辑十分复杂的话,修改会形成严重的逻辑问题。
税率计算的过程咱们定义一个抽象类Tax_cal,使用其进行税率的具体计算,不一样的计算规则在其子类中进行具体实现,经过这种方式可以有效地实现税率计算的功能。
运行代码为:函数
#include"strategy.h" int main() { bank_calcu bc(16000); bc.Calculate(new chinese_tax()); bc.Calculate(new Japanese()); std::cin.get(); }
结果为
Strategy模式的优势主要为:
一、相关算法系列
Strategy类层次为bank_calcu 定义了一系列可供重用的算法与行为。继承有助于析取出这些算法中的公共功能。
二、一个代替继承的方法
在代码中咱们还能够这样设计,也就是给bank_calcu 设计派生类,每一个派生类支持独有的算法,可是这样的派生类不只存在大量的代码重复,也就是未作到有效地复用,也会带来难以拓展与难以维护的问题。将算法封装在Strategy类中有利于理解与扩展。
三、消除了一些条件语句
Strategy提供了用条件语句选择所需的行为之外的另外一种选择。
四、实现了选择
Strategy 模式能够提供相同的行为的不一样实现。
其主要缺点为:
一、客户必需要了解不一样的Strategy
也就是说既然须要选择合适的Strategy就须要客户了解不一样的Strategy的区别在哪,这可能须要将策略的具体实现过程暴露给了用户。
二、Strategy与bank_calcu 的通讯开销
在本代码范例中Strategy的具体实现共享一个接口,可是实际状况下因为某些差别,入口参数并非全部的派生类成员函数都须要的,可是这种方式可以下降二者之间的耦合度;另外一种方法是将bank_calcu的引用做为参数传入,或者直接在Strategy存储一个bank_calcu引用,这样会形成必定程度的高耦合。
三、增长了对象的个数
Strategy虽然说消除了bank_calcu 中的代码臃肿与难以扩展的问题,可是其代价就是须要大量的类。
四、一些小的tip:
在进行Strategy的选择的时候须要传入一个具体Strategy指针,可是还有其余的办法,也就是经过模板,修改后的bank_calcu 能够经过模板选择:性能
template<class Tax_cal> class bank_calcu { public: bank_calcu(double); ~bank_calcu(); void Calculate(); private: double money; Tax_cal* tax_type;//保存一个Abstrategy指针 }; template<class Tax_cal> bank_calcu< Tax_cal>::bank_calcu(double money) :money(money) { tax_type = new Tax_cal();//给该指针分配内存 }; template<class Tax_cal> bank_calcu< Tax_cal>::~bank_calcu() { delete tax_type;//析构该内存 }; template<class Tax_cal> void bank_calcu< Tax_cal>::Calculate() { cout << tax_type->get_tax(money) << endl; } #endif // !STRATEGY
调用的过程为:编码
#include"strategy.h" int main() { bank_calcu<chinese_tax> t1(16000); t1.Calculate(); std::cin.get(); }
这样调用起来就更加顺手了。spa