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

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

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

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


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

查看所有标签

猜你喜欢:

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

Web Design in a Nutshell

Web Design in a Nutshell

Jennifer Niederst / O'Reilly Media, Inc. / 2006-02-21 / USD 34.99

Are you still designing web sites like it's 1999? If so, you're in for a surprise. Since the last edition of this book appeared five years ago, there has been a major climate change with regard to web......一起来看看 《Web Design in a Nutshell》 这本书的介绍吧!

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

在线压缩/解压 HTML 代码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具