设计模式(2)-策略模式之多用组合少用继承
2011-11-15 21:50
323 查看
设计模式(2)-策略模式之多用组合少用继承
首先看一下策略模式的意图
定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
结构
适用性
许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时[ H O 8 7 ] ,可以使用策略模式。
算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的S t r a t e g y 类中以代替这些条件语句。
这样看起来非常抽象,结合上个例子,修改一下程序的结构,根据策略模式。
类图如下
修改后程序如下,添加Context.h,Context.cpp,修改main
Context.h
Context.cpp
main
现在有个问题,switch又跑到客户端来处理了。
结合简单工厂优化一下代码吧!
修改后的程序如下
Context.h
Context.cpp
main
修改后,客户端的代码已经和原来一样了,还有一个很重要的一点,客户端现在只要处理一个Context对象就可以了,减少了代码之间的耦合。
策略模式封装了变化。
采用策略模式的好处主要有以下几点:
1.提供了管理相关的算法族的办法。
2.提供了可以替换继承关系的办法。
3.避免使用多重条件转移语句
但是它也自身的缺点:
1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
2.造成很多的策略类。
对于这种处理,可以将原来混在一起的继承有效的分离出来,将原来各种处理放到一个类中,即Context,下面再举一个例子说明一下吧。
首先看一下策略模式的意图
定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
结构
适用性
许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时[ H O 8 7 ] ,可以使用策略模式。
算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
一个类定义了多种行为, 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的S t r a t e g y 类中以代替这些条件语句。
这样看起来非常抽象,结合上个例子,修改一下程序的结构,根据策略模式。
类图如下
修改后程序如下,添加Context.h,Context.cpp,修改main
Context.h
class Context |
{ |
private : |
Operaton* operaton; |
public : |
Context(); |
Context(Operaton* oper); |
virtual ~Context(); |
virtual int getResult(); |
}; |
#include "stdafx.h" |
#include "Operaton.h" |
#include "Context.h" |
Context::Context(){ |
} |
Context::Context(Operaton* oper){ |
operaton = oper; |
} |
Context::~Context(){ |
} |
int Context::getResult(){ |
return operaton->getResult(); |
} |
#include "stdafx.h" |
#include <string> |
#include <iostream> |
#include "Operaton.h" |
#include "OperatonAdd.h" |
#include "OperatonDiv.h" |
#include "OperatonMul.h" |
#include "OperatonSub.h" |
#include "Context.h" |
using namespace std; |
int main( int argc, char * argv[]) |
{ |
int strNumA,strNumB; |
int strOperator; |
cout<< "请输入数字A:\n" ; |
cin>>strNumA; |
cout<< "请选择运算符号(1,+,2,-,3,*,4,/):\n" ; |
cin>>strOperator; |
cout<< "请输入数字B:\n" ; |
cin>>strNumB; |
int strResult = 0; |
Operaton *op; |
Context *context; |
switch (strOperator) |
{ |
case OPERATOR_ADD: |
op = new OperatonAdd(); |
break ; |
case OPERATOR_MINUS: |
op = new OperatonSub(); |
break ; |
case OPERATOR_MUTHL: |
op = new OperatonMul(); |
break ; |
case OPERATOR_DIV: |
op = new OperatonDiv(); |
break ; |
default : |
cout<< "输入有错误!" <<endl; |
break ; |
} |
op->numA = strNumA; |
op->numB = strNumB; |
context = new Context(op); |
strResult = context->getResult(); |
cout<< "得到的结果是:" <<strResult; |
return 0; |
} |
结合简单工厂优化一下代码吧!
修改后的程序如下
Context.h
#include "Operaton.h" |
#include "OperatonAdd.h" |
#include "OperatonDiv.h" |
#include "OperatonMul.h" |
#include "OperatonSub.h" |
class Context |
{ |
private : |
Operaton *op; |
public : |
Context(); |
Context( int strOperator); |
virtual ~Context(); |
virtual int getResult( int numA, int numB); |
}; |
#include "stdafx.h" |
#include "Context.h" |
Context::Context(){ |
} |
Context::Context( int strOperator){ |
switch (strOperator) |
{ |
case OPERATOR_ADD: |
op = new OperatonAdd(); |
break ; |
case OPERATOR_MINUS: |
op = new OperatonSub(); |
break ; |
case OPERATOR_MUTHL: |
op = new OperatonMul(); |
break ; |
case OPERATOR_DIV: |
op = new OperatonDiv(); |
break ; |
default : |
cout<< "输入有错误!" <<endl; |
break ; |
} |
} |
Context::~Context(){ |
} |
int Context::getResult( int numA, int numB){ |
return op->getResult(numA,numB); |
} |
#include "stdafx.h" |
#include <string> |
#include <iostream> |
#include "Context.h" |
using namespace std; |
int main( int argc, char * argv[]) |
{ |
int strNumA,strNumB; |
int strOperator; |
cout<< "请输入数字A:\n" ; |
cin>>strNumA; |
cout<< "请选择运算符号(1,+,2,-,3,*,4,/):\n" ; |
cin>>strOperator; |
cout<< "请输入数字B:\n" ; |
cin>>strNumB; |
int strResult = 0; |
Context *context; |
context = new Context(strOperator); |
strResult = context->getResult(strNumA,strNumB); |
cout<< "得到的结果是:" <<strResult; |
return 0; |
} |
策略模式封装了变化。
采用策略模式的好处主要有以下几点:
1.提供了管理相关的算法族的办法。
2.提供了可以替换继承关系的办法。
3.避免使用多重条件转移语句
但是它也自身的缺点:
1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
2.造成很多的策略类。
对于这种处理,可以将原来混在一起的继承有效的分离出来,将原来各种处理放到一个类中,即Context,下面再举一个例子说明一下吧。
相关文章推荐
- Java编程思想笔记02:组合与继承、final、策略设计模式与适配器模式、内部类、序列化控制(注意事项)
- Head First 设计模式--1策略模式 组合优于继承
- 设计模式(2)-策略模式之多用组合少用继承
- (转)组合优于继承---设计模式之策略模式
- 设计模式六种关系:依赖、关联、聚合、组合、继承和实现
- Template模式和策略模式区别,就是组合和继承区别
- [js高手之路]设计模式系列课程-组合模式+寄生组合继承实战新闻列表
- 设计模式---继承和组合
- java设计模式(工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式、适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式,。 行为型模式,共十一种:策略模式、模板方法)
- 设计模式之多用组合,少用继承
- [js高手之路]设计模式系列课程-组合模式+寄生组合继承实战新闻列表
- 简析设计模式之工厂模式与策略模式的实际组合应用
- java设计模式--策略模式--规避继承的耦合度大和接口的不能复用
- 设计模式学习(一):多用组合少用继承(C#)
- 类继承和对象组合(摘录设计模式)
- 设计模式---复合模式(策略-适配器-装饰者-抽象工厂-组合-观察者)
- 设计模式----优先使用对象组合,而非类继承
- 设计模式知识连载(7)---继承_3:优点结合-组合继承
- 设计模式推演——组合与继承
- 从头认识设计模式-策略模式-02-解决方向一:在继承里面增加导入导出方法