c++ 设计模式4 (Strategy)

3.2 Strategy (策略模式)

动机:在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂,而且有时候支持不使用或不常使用的算法也是一个性能负担。

如何在运行时根据需要透明地改变对象的算法?将算法和对象本身解耦,从而避免上述问题?

代码示例:

如果使用第一种方法,需要更改枚举类型和if else语句(第6行和24行),违背了开放封闭原则(对扩展开发,对修改封闭);

采用第二种方法(策略模式),定义税法基类,对不同国家税法定义不同子类,override Calculate方法。59行,多态调用。

假设出现变化:扩展32 - 39行,SalesOrder不变(复用性,遵循开放封闭原则)。

补:面向对象提到的复用性,指的是编译单位(二进制单位)的复用性,不是粘贴代码的复用性

 1 // strategy1.cpp
 2 enum TaxBase {
 3     CN_Tax,
 4     US_Tax,
 5     DE_Tax,
 6     FR_Tax       //更改
 7 };
 8
 9 class SalesOrder{
10     TaxBase tax;
11 public:
12     double CalculateTax(){
13         //...
14
15         if (tax == CN_Tax){
16             //CN***********
17         }
18         else if (tax == US_Tax){
19             //US***********
20         }
21         else if (tax == DE_Tax){
22             //DE***********
23         }
24         else if (tax == FR_Tax){  //更改
25             //...
26         }
27
28         //....
29      }
30   

 1 //Strategy.cpp
 2 class TaxStrategy{
 3 public:
 4     virtual double Calculate(const Context& context)=0;
 5     virtual ~TaxStrategy(){}
 6 };
 7
 8
 9 class CNTax : public TaxStrategy{
10 public:
11     virtual double Calculate(const Context& context){
12         //***********
13     }
14 };
15
16 class USTax : public TaxStrategy{
17 public:
18     virtual double Calculate(const Context& context){
19         //***********
20     }
21 };
22
23 class DETax : public TaxStrategy{
24 public:
25     virtual double Calculate(const Context& context){
26         //***********
27     }
28 };
29
30
31
32 //扩展
33 //*********************************
34 class FRTax : public TaxStrategy{
35 public:
36     virtual double Calculate(const Context& context){
37         //.........
38     }
39 };
40
41
42 class SalesOrder{
43 private:
44     TaxStrategy* strategy;
45
46 public:
47     SalesOrder(StrategyFactory* strategyFactory){
48         this->strategy = strategyFactory->NewStrategy();
49     }
50     ~SalesOrder(){
51         delete this->strategy;
52     }
53
54     public double CalculateTax(){
55         //...
56         Context context();
57
58         double val =
59             strategy->Calculate(context); //多态调用
60         //...
61     }
62
63 };

定义: 定义一系列算法, 把它们一个个封装起来,并且使它们可以互相替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)。

类图:

要点总结:

Strategy及其子类为组件提供了一系列可重用的算法,从而可以得到类型在运行时方便地根据需要在各个算法之间进行切换。

Strtegy模式提供了用条件判断语句以外的另一种选择消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式。(除非if else语句绝对不变,如对一周七天判断等)

如果Strategy对象没有实例变量,那么各个上下午可以共享同一个Strategy对象,从而节省对象开销。

时间: 2024-10-12 20:18:55

c++ 设计模式4 (Strategy)的相关文章

Design Pattern 设计模式1 - Strategy 1

实现 : Defferent Heros attack Defferently. - 不同的英雄使用不用的招数 Strategy设计的思路: 基类A,更加小的基类B,新的继承类C: 1 从基类A中抽出一个更加小的基类B 2 利用这个更加小的基类B实现不同的效果 3 把这个更加小的基类B包含进基类A中去 4 新的继承类C只需要和基类A打交道,设计不同行为,不需要理会更加小的基类B #pragma once #ifndef _STRATEGY_HEROS_H #define _STRATEGY_HE

设计模式之Strategy Pattern

Declaration 首先声明, 本篇blog的内容是参考Design pattern FAQ Part 3 ( Design pattern training series)这篇博文写的, 图片也是来自这篇博客. 部分是翻译, 加上自己的理解形成这篇博文. 希望和大家一起学习设计模式, 共同进步. Scene for Strategy Pattern Strategy Pattern,这个翻译成策略模式应该是没有问题的.策略模式希望做到的是在运行的情况下,根据对象的类型选择使用的算法.简单来

Java 设计模式(九) Strategy(策略)模式及Spring引申

Strategy 基本概念 策略模式(Strategy Pattern): 定义一组算法,将每个算法都封装起来,并且他们之间可以互换. 使用面向对象的继承和多态机制实现 Strategy中的角色: Context封装角色: 它叫做上下文角色,起承上启下的封装作用,屏蔽高层模块对策略.算法的直接访问,封装可能存在的变化. Strategy抽象策略角色: 策略,算法家族的抽象,通常为接口,定义每个策略或算法的必须具有的算法和属性. Concrete Strategy具体策略角色: 实现抽象策略中的操

JAVA设计模式十--strategy(策略者模式)

概念策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法独立于使用它的客户而独立变化.(原文:The Strategy Pattern defines a family of algorithms,encapsulates each one,and makesthem interchangeable. Strategy lets the algorithm vary independently from clients that use it.)Conte

《Head First设计模式(中文版)》

<Head First设计模式(中文版)>共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计模式.前言先介绍<Head First设计模式(中文版)>的用法:第1章到第11章陆续介绍的设计模式为Strategy.Observer.Decorator.Abstract Factory.Factory Method.Singleton,Command.Adapter.Facade.TemplateMethod.Iterator.Composite.State.P

菜鸟看设计模式系列笔记之开篇:设计模式的原则及概论

模式是在某一个背景下的某一个问题的解决方案. 设计模式在很大程度上是为了解决软件的可复用性,而根据大量工程实践总结出来的软件体系结构,隐含包括了软件工程的面向对象思想:封装.继承.多态. 为什么需要设计模式:设计模式(Design Pattern )是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结, 使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码的可靠性. 设计模式一般有如下几个基本要素:模式名称.问题.目的.解决方案.效果.实例代码和相关的设计模式,关键因素包

head first 设计模式pdf

下载地址:网盘下载 内容简介  · · · · · · <Head First设计模式>(中文版)共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计模式.前言先介绍这本书的用法:第1章到第11章陆续介绍的设计模式为Strategy.Observer.Decorator.Abstract Factory.Factory Method.Singleton,Command.Adapter.Facade.TemplateMethod.Iterator.Composite.Sta

Head First设计模式(中文版)pdf下载

非常值得推荐的一本书,不仅仅是学习设计模式,也是在推荐你编程能力的锻炼.简单易懂的例子,能让你学到非常多的知识.需要学习的朋友可以通过网盘免费下载pdf版 (先点击普通下载-----再选择普通用户就能免费下载了)http://putpan.com/fs/0yiabe3ns2hu69f37/ <Head First设计模式>(中文版)共有14章,每章都介绍了几个设计模式,完整地涵盖了四人组版本全部23个设计模式.前言先介绍这本书的用法:第1章到第11章陆续介绍的设计模式为Strategy.Obs

c++ virturn function -- 虚函数

pure irtual function  -- 纯虚函数 先看例子 #include <iostream> using namespace std; class Polygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b; } virtual int area() = 0 ;//{return 0;} // _vptr.Polygon show difre

JAVA学习-面试题小结

1)transient和volatile是java关键字吗?(瞬联) 如果用transient声明一个实例变量,当对象存储时,它的值不需要维持.例如: class T { transient int a;  //不需要维持 int b;  //需要维持 } 这里,如果T类的一个对象写入一个持久的存储区域,a的内容不被保存,但b的将被保存. volatile修饰符告诉编译器被volatile修饰的变量可以被程序的其他部分改变.在多线程程序中,有时两个或更多的线程共享一个相同的实例变量.考虑效率问题