/************************************************************************ * 策略模式学习笔记[C++] * Author: 陈相礼 * Time: 2009.12.02 * Compiler: VC8 ************************************************************************/ #include "StrategyPattern.h" #include "StrategyPattern1.h" #include <iostream> using namespace std; int main() { //------------------策略原理类测试------------------- Context *context; context = new Context( new ConcreteStrategyA() ); context->vContextInterface(); context = new Context( new ConcreteStrategyB() ); context->vContextInterface(); context = new Context( new ConcreteStrategyC() ); context->vContextInterface(); delete(context); //------------------策略类测试------------------- CashContext *cs; double dwMoney; cs = new CashContext( new CashNormal() ); dwMoney = cs->dwGetResult( 700 ); cs = new CashContext( new CashRebate( 0.8 ) ); dwMoney = cs->dwGetResult( 700 ); cs = new CashContext( new CashReturn( 300, 100 ) ); dwMoney = cs->dwGetResult( 700 ); delete(cs); //------------------简单工厂+策略类测试------------------- CashContextF *csf; csf = new CashContextF( 'N' ); dwMoney = csf->dwGetResult( 700 ); csf = new CashContextF( 'R' ); dwMoney = csf->dwGetResult( 700 ); csf = new CashContextF( 'T' ); dwMoney = csf->dwGetResult( 700 ); delete(csf); return 0; } /************************************************************************ * 总结: * 1、策略模式是一种定义一系列算法的方法,从概念上看所有这些算法 * 完成的都是相同的工作,只是实现不同,它可以以相同的方式调用 * 所有算法,减少了各种算法类与算法类之间的耦合。 * 2、策略模式的Strategy类层次为Context定义了一系列可供重用的算法 * 或行为。继承有助于吸取出这些算法中的公共功能。 * 3、策略模式的优点是简化了单元测试,因为每个算法都有自己的类, * 可以通过自己的接口单独测试。 * 4、当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择 * 合适的行为。将这些行为疯长在一个个独立的Strategy类中,可以在 * 使用这些行为的类中消除条件语句。 * 5、策略模式是用来封装算法的,但在实践中,它可以封装几乎任何类 * 型的规则,只要在分析过程中听到需要在不同时间应用不同的业务 * 规则,就可以考虑使用策略模式处理这种变化的可能性。 * 6、基本的策略模式中,选择所用具体实现职责由客户端对象承担,并 * 转给策略模式的Context对象。 * 7、任何需求的变更都是需要成本的。 ************************************************************************/ /************************************************************************ * 类的设计:单一职责原则 * 1、就一个类而言,应该仅有一个引起它变化的原因。 * 2、如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个 * 职责的变化可能削弱或者抑制这个类完成其他职责的能力。这种耦 * 合会导致脆弱的设计,当变化发生时,设计会遭到意想不到的破坏。 * 3、软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离 * 4、如果你能想到多余一个的动机去改变一个类,那么这个类就具有多于 * 一个职责,就应该考虑类的职责分离。 ************************************************************************/ /************************************************************************ * 类的设计:开放-封闭原则 * 1、软件实体(类、模块、函数等)应该可以扩展,但是不可修改。 * 2、此原则保证对需求的改变却可以保持相对稳定,从而使得系统可以 * 在第一个版本以后不断推出新的版本。 * 3、无论模块是多么的“封闭”,都会存在一些无法对之封闭的变化。既然 * 不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封 * 闭作出选择。他必须先猜测出最有可能发生的变化种类,然后构造抽 * 象来隔离那些变化。 * 4、在我们最初编写代码时,假设变化不会发生。当变化发生时,我们就 * 创建抽象来隔离以后发生的同类变化。 * 5、面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有 * 的代码。 * 6、我们希望的是在开发工作展开不久就知道可能发生的变化。查明可能 * 发生的变化所等待的时间越长,要创建正确的抽象就越困难。 * 7、开放-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来 * 面向对象技术所声称的巨大好处,也就是可维护、可扩展、可复用、 * 灵活性好。开发人员应该仅对程序中呈现出频繁变化的那些部分作出 * 抽象,然而,对于应用程序中的每个部分都刻意地进行抽象同样不是 * 一个好主意。拒绝不成熟的抽象和抽象本身一样重要。切记! ************************************************************************/ /************************************************************************ * 类的设计:依赖倒转原则[谁也不依赖谁] * 1、(1) 高层模块不应该依赖低层模块。两个都应该依赖抽象。 * (2) 抽象不应该依赖细节,细节应该依赖抽象。即针对接口编程,不 * 要对实现编程。 * 2、里氏代换原则[LSP]:一个软件实体如果使用的是一个父类的话,那么 * 一定适用于其子类,而且它察觉不出父类对象和子类对象的区别。也 * 就是说,在软件里面,把父类都替换成它的子类,程序的行为无变化。 * 3、只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才 * 能真正被复用,而子类也能够在父类的基础上增加新的行为。 * 4、由于子类型的可替换性才使得使用父类型的模块在无需修改的情况下 * 就可以扩展。 * 5、依赖倒转其实可以说是面向对象设计的标志,用哪种语言来编写程序 * 不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编 * 程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面 * 向对象的设计,反之那就是过程化的设计了。 ************************************************************************/ #pragma once /********************************************** * 策略模式原理: * 定义算法家族,分别封装起来,让它们 * 之间可以相互替换,此模式让算法的变 * 化,不会影响到使用算法的用户。 ***********************************************/ #include <iostream> using namespace std; //--------------------------------------------- // 抽象算法类 // 定义所有支持的算法的公共接口 class Strategy { public: // 算法方法 virtual void vAlgorithmInterface(){}; protected: private: }; //--------------------------------------------- // 具体策略类 // 继承于算法类,封装具体的算法或行为 // 算法A的实现 class ConcreteStrategyA : public Strategy { public: void vAlgorithmInterface() { cout << "算法A的实现" << endl; } protected: private: }; // 算法B的实现 class ConcreteStrategyB : public Strategy { public: void vAlgorithmInterface() { cout << "算法B的实现" << endl; } protected: private: }; // 算法C的实现 class ConcreteStrategyC : public Strategy { public: void vAlgorithmInterface() { cout << "算法C的实现" << endl; } protected: private: }; //--------------------------------------------- // Context上下文类 // 用一方法维护对Strategy对象的引用 // 上下文 class Context { public: // 初始化传入具体策略对象 Context( Strategy *pstrategy ) : mp_strategy(pstrategy) {}; // 上下文接口 // 根据具体策略对象调用其算法的方法 void vContextInterface() { mp_strategy->vAlgorithmInterface(); } protected: private: Strategy *mp_strategy; }; #pragma once /******************************** * * 策略模式应用:商场收银<mce:script type="text/javascript" src="http://hi.images.csdn.net/js/blog/tiny_mce/themes/advanced/langs/zh.js" mce_src="http://hi.images.csdn.net/js/blog/tiny_mce/themes/advanced/langs/zh.js"></mce:script><mce:script type="text/javascript" src="http://hi.images.csdn.net/js/blog/tiny_mce/plugins/syntaxhl/langs/zh.js" mce_src="http://hi.images.csdn.net/js/blog/tiny_mce/plugins/syntaxhl/langs/zh.js"></mce:script>系统 * ********************************/ // 现金收费抽象类 class CashSuper { public: // 构造 CashSuper() : dwTotal(0) {}; virtual double dwAcceptCash( double dwMoney ) { dwTotal = dwMoney; return dwTotal; } protected: private: // 总价 double dwTotal; }; // 正常收费子类 class CashNormal : public CashSuper { public: double dwAcceptCash( double dwMoney ) { // 正常收费,原价返回 return dwMoney; } protected: private: }; // 打折收费子类 class CashRebate : public CashSuper { public: CashRebate() : dwMoneyRebate(1){}; CashRebate( double dwMoney ) : dwMoneyRebate(dwMoney) {}; double dwAcceptCash( double dwMoney ) { return dwMoney * dwMoneyRebate; } protected: private: double dwMoneyRebate;// 折扣率 }; // 返利收费子类 class CashReturn : public CashSuper { public: CashReturn() : dwMoneyCondition(300), dwMoneyReturn(100) {}; CashReturn( double dwCondition, double dwReturn ) : dwMoneyCondition(dwCondition), dwMoneyReturn(dwReturn) {}; double dwAcceptCash( double dwMoney ) { double dwResult = dwMoney; if ( dwMoney > dwMoneyCondition ) { // 大于返利条件 dwResult = dwMoney - (int)dwMoney / (int)dwMoneyCondition * dwMoneyReturn; } return dwResult; } protected: private: double dwMoneyCondition; double dwMoneyReturn; }; // 上下文 class CashContext { public: // 构造方法获取具体收费策略 CashContext( CashSuper *p_cs ) : mp_cashsuper(p_cs) {}; double dwGetResult( double dwMoney ) { // 根据收费策略的不同取得收费结果 return mp_cashsuper->dwAcceptCash( dwMoney ); } protected: private: // 加入CashSuper对象,聚合关系 CashSuper *mp_cashsuper; }; //--------------------------------------------- // 策略与简单工厂结合 class CashContextF { public: // 构造方法获取具体收费策略 CashContextF( char cType ) { switch ( cType ) { // 正常 case 'n': case 'N': mp_cashsuper = new CashNormal(); break; // 返利 case 'r': case 'R': mp_cashsuper = new CashReturn( 300, 100 ); break; // 打折 case 't': case 'T': mp_cashsuper = new CashRebate( 0.8 ); break; default: mp_cashsuper = new CashSuper(); break; } }; double dwGetResult( double dwMoney ) { // 根据收费策略的不同取得收费结果 return mp_cashsuper->dwAcceptCash( dwMoney ); } protected: private: // 加入CashSuper对象,聚合关系 CashSuper *mp_cashsuper; }; ——By 陈相礼 09/12/02