内容简介:动机:在软件构建的过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂,增加与改变现有算法可能带来严重的逻辑问题;而且有时候支持不使用的算法也是一个性能上的负担(具体上体现在代码太长会使得其在保存的位置出现问题),因此将对象与算法解耦,避免上述问题才是本算法动机。意图:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。本模式使得算法可独立于使用它的客户而改变。2、分析
1、动机与意图
动机:在软件构建的过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂,增加与改变现有算法可能带来严重的逻辑问题;而且有时候支持不使用的算法也是一个性能上的负担(具体上体现在代码太长会使得其在保存的位置出现问题),因此将对象与算法解耦,避免上述问题才是本算法动机。
意图:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。本模式使得算法可独立于使用它的客户而改变。
2、分析
示例代码:
#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语句来进行区别,但是依旧存在问题:
1、用不到的代码块就应该被去除,否则影响执行效率;
2、违反了开闭原则(对增加开放,对修改封闭);
3、容易出错,现在的逻辑还没有那么复杂,判断逻辑十分复杂的话,修改会造成严重的逻辑问题。
税率计算的过程我们定义一个抽象类Tax_cal,使用其进行税率的具体计算,不同的计算规则在其子类中进行具体实现,通过这种方式能够有效地实现税率计算的功能。
运行代码为:
#include"strategy.h" int main() { bank_calcu bc(16000); bc.Calculate(new chinese_tax()); bc.Calculate(new Japanese()); std::cin.get(); }
结果为
Strategy模式的优点主要为:
1、相关算法系列
Strategy类层次为bank_calcu 定义了一系列可供重用的算法与行为。继承有助于析取出这些算法中的公共功能。
2、一个代替继承的方法
在代码中我们还可以这样设计,也就是给bank_calcu 设计派生类,每个派生类支持独有的算法,但是这样的派生类不仅存在大量的代码重复,也就是未做到有效地复用,也会带来难以拓展与难以维护的问题。将算法封装在Strategy类中有利于理解与扩展。
3、消除了一些条件语句
Strategy提供了用条件语句选择所需的行为以外的另一种选择。
4、实现了选择
Strategy 模式可以提供相同的行为的不同实现。
其主要缺点为:
1、客户必须要了解不同的Strategy
也就是说既然需要选择合适的Strategy就需要客户了解不同的Strategy的区别在哪,这可能需要将策略的具体实现过程暴露给了用户。
2、Strategy与bank_calcu 的通信开销
在本代码范例中Strategy的具体实现共享一个接口,但是实际情况下由于某些差异,入口参数并不是所有的派生类成员函数都需要的,但是这种方式能够降低两者之间的耦合度;另一种方法是将bank_calcu的引用作为参数传入,或者直接在Strategy存储一个bank_calcu引用,这样会造成一定程度的高耦合。
3、增加了对象的个数
Strategy虽说消除了bank_calcu 中的代码臃肿与难以扩展的问题,但是其代价就是需要大量的类。
4、一些小的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(); }
这样调用起来就更加顺手了。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 设计模式——订阅模式(观察者模式)
- 设计模式-简单工厂、工厂方法模式、抽象工厂模式
- java23种设计模式-门面模式(外观模式)
- 设计模式-享元设计模式
- Java 设计模式之工厂方法模式与抽象工厂模式
- JAVA设计模式之模板方法模式和建造者模式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web信息架构(第3版)
Peter Morville、Louis Rosenfeld / 陈建勋 / 电子工业出版社 / 2008年8月 / 85.00
本书涵盖了信息架构基本原理和实践应用的方方面面。全书共7个部分,包括信息架构概述、信息架构的基本原理、信息架构的开发流程和方法论、信息架构实践、信息架构与组织、两个案例研究,以及参考资料清单。 本书兼具较高的理论价值和实用价值,曾被Web设计领域多本书籍重点推荐,是信息架构领域公认的经典书,不论新手还是专家都能各取所需。本书可供Web设计与开发者、Web架构师、网站管理者及信息管理相关人员参......一起来看看 《Web信息架构(第3版)》 这本书的介绍吧!