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

栏目: 后端 · 发布时间: 6年前

内容简介:动机:在软件构建的过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂,增加与改变现有算法可能带来严重的逻辑问题;而且有时候支持不使用的算法也是一个性能上的负担(具体上体现在代码太长会使得其在保存的位置出现问题),因此将对象与算法解耦,避免上述问题才是本算法动机。意图:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。本模式使得算法可独立于使用它的客户而改变。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(策略模式)

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

这样调用起来就更加顺手了。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming Python

Programming Python

Mark Lutz / O'Reilly Media / 2006-8-30 / USD 59.99

Already the industry standard for Python users, "Programming Python" from O'Reilly just got even better. This third edition has been updated to reflect current best practices and the abundance of chan......一起来看看 《Programming Python》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具