设计模式(2)-策略模式之多用组合少用继承

首先看一下策略模式的意图

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

结构


适用性

许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时[ 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();

};

Context.cpp

#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();
}

main

#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;
}

现在有个问题,switch又跑到客户端来处理了。

结合简单工厂优化一下代码吧!

修改后的程序如下

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);

};

Context.cpp

#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);
}

main

#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;
}

修改后,客户端的代码已经和原来一样了,还有一个很重要的一点,客户端现在只要处理一个Context对象就可以了,减少了代码之间的耦合。

策略模式封装了变化。

采用策略模式的好处主要有以下几点:
1.提供了管理相关的算法族的办法。
2.提供了可以替换继承关系的办法。
3.避免使用多重条件转移语句
但是它也自身的缺点:
1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
2.造成很多的策略类。

对于这种处理,可以将原来混在一起的继承有效的分离出来,将原来各种处理放到一个类中,即Context,下面再举一个例子说明一下吧。

时间: 2025-01-11 12:24:08

设计模式(2)-策略模式之多用组合少用继承的相关文章

JavaScript设计模式之策略模式

在网上搜索"为什么MVC不是一种设计模式呢?"其中有解答:MVC其实是三个经典设计模式的演变:观察者模式(Observer).策略模式(Strategy).组合模式(Composite).所以我今天选择学习策略模式. 策略模式:定义了一系列家族算法,并对每一种算法单独封装起来,让算法之间可以相互替换,独立于使用算法的客户. 通常我并不会记得"牛顿第一定律"的具体内容,所以我也难保证我会对这个定义记得多久--用FE经常见到的东西来举个例子说明一下: $("d

深入理解JavaScript系列(33):设计模式之策略模式详解

 这篇文章主要介绍了深入理解JavaScript系列(33):设计模式之策略模式详解,策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户,需要的朋友可以参考下     介绍 策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户. 正文 在理解策略模式之前,我们先来一个例子,一般情况下,如果我们要做数据合法性验证,很多时候都是按照swith语句来判断,但是这就带来几个问题,首先如果增加需求的话

乐在其中设计模式(C#) - 策略模式(Strategy Pattern)

原文:乐在其中设计模式(C#) - 策略模式(Strategy Pattern)[索引页][源码下载] 乐在其中设计模式(C#) - 策略模式(Strategy Pattern) 作者:webabcd 介绍 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法的变化可独立于使用它的客户. 示例 有一个Message实体类,对它的操作有Insert()和Get()方法,持久化数据在SqlServer数据库中或Xml文件里(两种可互换的算法).由客户端决定使用哪种算法. Me

设计模式之五(策略模式)

原文:设计模式之五(策略模式) 前言 策略模式:它定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户. 策略模式结构图   Strategy:策略类,定义所有支持的算法的公共接口 ConcreteStrategy1,ConcreteStrategy2,ConcreteStrategy3这三个是具体策略类,封装了具体的算法或行为,继承于Strategy Context上下文,用一个ConcreteStrategy来配置,维护一个对Strategy对象

设计模式:策略模式(Strategy)

定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法可独立于使用它的客户而变化. 策略模式的角色: 1. 抽象策略角色(Strategy):策略类,通常由一个接口或者抽象类实现 2. 具体策略角色(ConcreteStrategy):包装了相关的算法和行为 3. 环境角色(Context):持有一个策略类的引用,最终给客户端调用 这里引用参考资料3中的例子来详细说明一下策略模式. "赔了夫人又折兵"--这个是<三国演义>里的著名桥段,主要是说刘备要去

【设计模式】—— 策略模式Strategy

模式意图 定义一系列的算法,把他们封装起来,使得算法独立于适用对象. 比如,一个系统有很多的排序算法,但是使用哪个排序算法是客户对象的自有.因此把每一个排序当做一个策略对象,客户调用哪个对象,就使用对应的策略方法. 应用场景 1 当许多的类,仅仅是行为或者策略不同时,可以把行为或策略单独提取出来,这样主体的类就可以进行统一了. 2 需要使用不同的算法. 3 一个类定义了多种行为. 模式结构 Context 环境角色的,策略的调用者 class Context{ private Strategy

Head First设计模式之策略模式

这是学习的第一个设计模式,而书中写的实例相对比较复杂,参考了网上的文章进行总结 一.定义   策略模式(strategy pattern): 定义了算法族, 分别封闭起来, 让它们之间可以互相替换, 此模式让算法的变化独立于使用算法的客户.   策略模式是针对一组算法,将每个算法封装到具有公共接口的独立的类中,从而使它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 设计原则一 找出应用中需要变化之处,把它们独立出来.不要和那些不需要变化的代码混在一起 设计原则二 针对接口

php设计模式之策略模式

策略模式: 策略模式是对象的行为模式,用意是对一组算法的封装.动态的选择需要的算法并使用. 策略模式指的是程序中涉及决策控制的一种模式.策略模式功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多形性思想. 策略模式的三个角色: 1.抽象策略角色 2.具体策略角色 3.环境角色(对抽象策略角色的引用) 实现步骤: 1.定义抽象角色类(定义好各个实现的共同抽象方法) 2.定义具体策略类(具体实现父类的共同方法) 3.定义环境角色类(私有化申明抽象角色变量,重载构造方法,执行抽象方法)

关于.NET Framework中的设计模式--应用策略模式为List排序_实用技巧

简单类型排序 编程时遇到排序在平常不过,使用.Net最常见的就是对泛型List<T>进行排序,如果T是简单数据类型排序那么很简单 复制代码 代码如下: public List<int> SortSimpleList(List<int> list){list.Sort();return list;} 同样对string等简单类型List<T>排序均如此,如果我们要排的对象复杂了怎么办,我们知道List<T> sort()最后是用快速排序实现,快速排