用C++跟你聊聊“策略模式”
说实话上一篇的“简单工厂模式”,我觉得不是很满意。 虽然网上大部分都是用Java写的设计模式,但是我竟然是用“伪代码”写的。。
所以我决定,接下来的每篇设计模式都用C++亲测。
一个简单的超市促销活动
现在需要你为商场做一个促销计算器,促销种类包括:不促销、打折、消费返利。
你会如何操作呢?
讨论过了上一节的简单工厂模式,我觉得应该不至于把类设计的太死板了。 但是简单工厂模式有一个明显的缺点,就是会暴露出过多的接口,而且代码重用度也不是很理想的。
不卖关子了啊,题目都写在那儿了,今天我们来聊聊 - ”策略模式“。
要聊”策略模式“,咱首先得有共同语言。昨天讲UML的时候有一个名词我现在还记忆犹新:抽象基类。此时可能一群不了解没听说过或者不了解抽象基类的朋友准备骂骂咧咧退出群聊了哈。少安勿躁。
抽象基类
什么是抽象基类?就是把n个类,抽出共同特征,然后组成一个基类。这些共同特征,可以是类属性,也可以是类方法。
比方说猫类、狗类和鸟类,它们就可以抽象出:它们都是动物、它们都会叫、都会吃喝拉沙睡···把这些共同点有机组合成一个类,就是抽象基类,就叫ABC类吧。
然后呢,猫类、狗类、鸟类都继承于ABC类。
这样有什么好处呢?有的,统筹兼顾。怎么个统筹兼顾法,别急往下看。
回到上面那个超市促销活动,那个活动有什么共通点?或者说,那些促销方式有什么共同点?有的,最后都要结账的,不能拎着东西你就跑吧。
超市促销活动的UML策略模式类图
策略模式实现
刚刚说不了解抽象基类的朋友先别急,如果实在不了解抽象基类,可以看一下这里的代码。
如何判断一个类是否为抽象基类呢?就看它有没有纯虚函数。
而且,如果是抽象基类的话,是不能引用类对象,万年单身狗啊。
#include<iostream>
using namespace std;
//抽象基类
class cashbase
{
public:
virtual double accept_cash(double money) = 0;
};
//各个子类
class cashnormal: public cashbase
{
public:
double accept_cash(double money) { return money; } //原价返回
};
class cashrebate: public cashbase
{
private:
double rebate;
public:
cashrebate(double rebate) { this->rebate = rebate; }
double accept_cash(double money) { return money * this->rebate; }
};
class cashreturn: public cashbase
{
private:
double moneycondition = 0.0;
double moneyreturn = 0.0;
public:
cashreturn(double moneycondition, double moneyreturn)
{
this->moneycondition = moneycondition;
this->moneyreturn = moneyreturn;
}
double accept_cash(double money)
{
if (money >= this->moneycondition)
return (money - this->moneyreturn);
else
return money;
}
};
//早期模式工厂
//class cashcontex
//{
//private:
// cashbase *cb; //这不是类引用对象
//public:
// cashcontex(cashbase* cb) { this->cb = cb; }//将收费策略作为参数传入
// double getresult(double money) { return cb->accept_cash(money); }
//
//};
//由于会绕回工厂模式的老路,故取消这种做法
class cashcontex
{
private:
cashbase* cb = NULL;//这是指针对象
public:
cashcontex(int type, double rebate, double moneycondition, double moneyreturn)
{
if (type == 0)
{
cashnormal* cn = new cashnormal();
cb = cn;
}
else if (type == 1)
{
cashrebate* cr = new cashrebate(rebate);
cb = cr;
}
else if (type == 2)
{
cashreturn* crt = new cashreturn(moneycondition, moneyreturn);
cb = crt;
}
}
double getresult(double money){return cb->accept_cash(money);}
};
int main()
{
cashcontex* cc = new cashcontex(1, 0.6, 0, 0);
double ret = cc->getresult(300.0);
cout << ret << endl;
return 0;
}
上面这套代码呢,其实是策略模式和简单工厂的结合。
回顾策略模式
策略模式通过 定义一系列算法的方法,减少各种算法类与使用算法类之间的耦合(上面那个main,只能姐醋到一个cashcontex类)。
策略模式简化了单元测试,因为每个算法都有自己的类,可以通过自己的借口单独测试。就算某个算法出问题,也不会影响到其他的算法。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- MySQL8.0.18 试用Hash Join
- InnoDB:表空间管理
- MyBatis 增删改查
- python分析wav文件
- CICD实战——服务自动构建与部署
- python+opencv实时视频目标检测
- python数据化运营分析实例---销售预测
- Leetcode 1444. 切披萨的方案数(DP,类似石材切割,二维前缀和)
- Python生成内涵图片
- Linux 下makefile实战 ——编写真实的C项目
- MySQL8功能详解——Common table expression (CTE)
- 游戏数据分析
- MySQL8功能详解——隐藏索引
- python 操作excel(附案例)
- 如何在 Spring Boot 中 读写数据