目录
策略模式
基本简介
策略模式(StrategyModel)是一种 定义一系列算法 的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以 以相同的方式 调用所有的算法,减少了各种算法类与使用算法类之间的耦合[DPE]。
使用场景
一个系统有许多类,区分他们的只是直接行为不同时。
应用实例
出行方式,自行车、汽车等,每一种出行方式都是一个策略
商场促销方式,打折、满减等
优点
减少了各种算法类与使用算法类之间的耦合[DPE]
策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能[DP]
缺点
策略类数量会增多,每个策略都是一个类,复用的可能性很小
所有的策略类都需要对外暴露
※如果一个系统的策略多于四个,就需要考虑使用混合模式来解决策略类膨胀的问题
实例
本实例还是基于商场收银软件(qt实现),相关内容见day01中
Strategy头文件
#include<QString>
/**
* @brief 现金收费抽象类、抽象基类
* @param
* @return
*/
class CashSuper{
public:
/**
* @brief 现金收取类的纯虚函数,收取现金
* @param 原价
* @return 当前价
*/
virtual double AcceptCash(double money)=0;
};
/**
* @brief 正常收费子类
* @param
* @return
*/
class CashNormal:public CashSuper{
public:
//正常收费,原价返回
double AcceptCash(double money) override;
};
/**
* @brief 打折收费子类
* @param
* @return
*/
class CashRebate:public CashSuper{
public:
CashRebate(double moneyRebate);//打折收费,初始化时输入折扣率
double AcceptCash(double money) override;
private:
double moneyRate=1;
};
/**
* @brief 返利收费子类,初始化时输入返利条件和返利值
* @param 返利条件moneyCondition 返利值moneyReturn
* @return
*/
class CashReturn:public CashSuper{
public:
CashReturn(double moneyCondition,double moneyReturn);
double AcceptCash(double money) override;
private:
double moneyCondition=0.0;
double moneyReturn=0.0;
};
Strategy源文件
double CashNormal::AcceptCash(double money)
{
return money;
}
CashRebate::CashRebate(double moneyRebate)
{
if(moneyRebate>1||moneyRebate<0){
throw "rate error";
}
this->moneyRate=moneyRebate;
}
double CashRebate::AcceptCash(double money)
{
return money*moneyRate;
}
CashReturn::CashReturn(double moneyCondition, double moneyReturn)
{
this->moneyCondition=moneyCondition;
this->moneyReturn=moneyReturn;
}
double CashReturn::AcceptCash(double money)
{
double result=money;
if(money>=moneyCondition){
result=money-moneyReturn;
}
return result;
}
context上下文
#include"Strategy.h"
/**
* @brief 上下文 策略模式实现
* @param
* @return
*/
class CashContext
{
public:
CashContext(CashSuper* csuper);
/**
* @brief 根据收费策略的不同,获得计算结果
* @param 原价
* @return 折扣后的价格
*/
double getResult(double money);
private:
CashSuper* cs;
};
#include "cashcontext.h"
CashContext::CashContext(CashSuper* csuper)
{
this->cs=csuper;
}
double CashContext::getResult(double money)
{
return cs->AcceptCash(money);
}
客户端代码
void Widget::on_btn_ok_clicked()//点击确定槽函数
{
double total=0.00;//声明一个double变量total来计算总计
double price=ui->line_Price->text().toDouble();//lineEdit获取price
double num=ui->line_Num->text().toDouble();//lineEdit获取num
total=num*price;//获取合计
CashContext *cs=nullptr;
switch (ui->comboBox->currentIndex()) {
case 0:
cs=new CashContext(new CashNormal()); //正常收费
break;
case 1:
cs=new CashContext(new CashReturn(300,100)); //满300减100
break;
case 2:
cs=new CashContext(new CashRebate(0.8)); //打8折
break;
case 3:
cs=new CashContext(new CashRebate(0.5));//打五折
break;
case 4:
cs=new CashContext(new CashReturn(500,200));//满500减200
break;
default:
break;
}
total=cs->getResult(total);
ui->listWidget->addItem("单价:"+ui->line_Price->text()+
" 数量:"+ui->line_Num->text()+
" "+ui->comboBox->currentText()+
" 合计:"+QString::number(total));//添加到啊listWidget中
ui->labShowPrice->setText(QString::number(total));//显示到lab中。
}
结合简单工厂模式的策略模式
利用简单工厂将判断的过程从客户端程序转移走,实现算法和客户端分离。
context上下文
#include"Strategy.h"
/**
* @brief 上下文 策略模式实现
* @param
* @return
*/
class CashContext
{
public:
CashContext(int type);
/**
* @brief 根据收费策略的不同,获得计算结果
* @param 原价
* @return 折扣后的价格
*/
double getResult(double money);
private:
CashSuper* cs;
};
#include "cashcontext.h"
CashContext::CashContext(int type)
{
switch (type) {
case 0:
cs= new CashNormal(); //正常收费
break;
case 1:
cs=new CashReturn(300,100); //满300减100
break;
case 2:
cs=new CashRebate(0.8); //打8折
break;
case 3:
cs=new CashRebate(0.5);//打五折
break;
case 4:
cs=new CashReturn(500,200);//满500减200
break;
default:
break;
}
}
double CashContext::getResult(double money)
{
return cs->AcceptCash(money);
}
客户端
void Widget::on_btn_ok_clicked()//点击确定槽函数
{
double total=0.00;//声明一个double变量total来计算总计
double price=ui->line_Price->text().toDouble();//lineEdit获取price
double num=ui->line_Num->text().toDouble();//lineEdit获取num
total=num*price;//获取合计
//根据下拉框吗,将相应的算法的索引传入到CashContext对象中
CashContext *cs=new CashContext(ui->comboBox->currentIndex());
total=cs->getResult(total);
ui->listWidget->addItem("单价:"+ui->line_Price->text()+
" 数量:"+ui->line_Num->text()+
" "+ui->comboBox->currentText()+
" 合计:"+QString::number(total));//添加到啊listWidget中
ui->labShowPrice->setText(QString::number(total));//显示到lab中。
}
void Widget::on_btn_ok_2_clicked()
{
ui->listWidget->clear();
ui->labShowPrice->setText("0.00");
}