C++策略模式

来源:互联网 发布:黑莓classic转制软件 编辑:程序博客网 时间:2024/05/29 18:50
设计模式(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();
 
    virtualintgetResult();
 
};

Context.cpp

#include "stdafx.h"
#include "Operaton.h"
#include "Context.h"
 
 
Context::Context(){
 
}
 
Context::Context(Operaton* oper){
    operaton = oper;
}
 
Context::~Context(){
 
}
 
int Context::getResult(){
    returnoperaton->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(intargc,char* argv[])
{
    intstrNumA,strNumB;
    intstrOperator;
    cout<<"请输入数字A:\n";
    cin>>strNumA;
    cout<<"请选择运算符号(1,+,2,-,3,*,4,/):\n";
    cin>>strOperator;
    cout<<"请输入数字B:\n";
    cin>>strNumB;
 
    intstrResult = 0;
    Operaton *op;
    Context *context;
     
    switch(strOperator)
    {
        caseOPERATOR_ADD:
            op =newOperatonAdd();
            break;
        caseOPERATOR_MINUS:
            op =newOperatonSub();
            break;
        caseOPERATOR_MUTHL:
            op =newOperatonMul();
            break;
        caseOPERATOR_DIV:
            op =newOperatonDiv();
            break;
        default:
            cout<<"输入有错误!"<<endl;
            break;
    }
 
    op->numA = strNumA;
    op->numB = strNumB;
    context =newContext(op);
    strResult = context->getResult();
    cout<<"得到的结果是:"<<strResult;
    return0;
}

现在有个问题,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(intstrOperator);
    virtual~Context();
 
    virtualintgetResult(intnumA,intnumB);
 
};

Context.cpp

#include "stdafx.h"
#include "Context.h"
 
Context::Context(){
 
}
 
Context::Context(intstrOperator){
    switch(strOperator)
    {
        caseOPERATOR_ADD:
            op =newOperatonAdd();
            break;
        caseOPERATOR_MINUS:
            op =newOperatonSub();
            break;
        caseOPERATOR_MUTHL:
            op =newOperatonMul();
            break;
        caseOPERATOR_DIV:
            op =newOperatonDiv();
            break;
        default:
            cout<<"输入有错误!"<<endl;
            break;
    }
}
 
Context::~Context(){
 
}
 
int Context::getResult(intnumA,intnumB){
    returnop->getResult(numA,numB);
}

main

#include "stdafx.h"
#include <string>
#include <iostream>
#include "Context.h"
 
using namespace std;
 
int main(intargc,char* argv[])
{
    intstrNumA,strNumB;
    intstrOperator;
    cout<<"请输入数字A:\n";
    cin>>strNumA;
    cout<<"请选择运算符号(1,+,2,-,3,*,4,/):\n";
    cin>>strOperator;
    cout<<"请输入数字B:\n";
    cin>>strNumB;
 
    intstrResult = 0;
     
    Context *context;
    context =newContext(strOperator);
    strResult = context->getResult(strNumA,strNumB);
    cout<<"得到的结果是:"<<strResult;
    return0;
}

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

策略模式封装了变化。

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

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


原创粉丝点击