## 订单处理系统
考虑这样一个应用场景:
现在有一个订单处理系统,里面有一个保存订单的业务功能,在这个业务功能中,客户有这样一个需求:每当订单的预定产品数量超过1000的时候,就需要把订单拆成两份订单来保存。如果拆成两份订单后,还是超过1000,那就继续拆,直到每份订单的预定产品数量不超过1000。至于为什么要拆分,原因是方便进行订单的后续处理,每个人工工作小组的处理能力上限是1000。
根据业务,目前的订单类型分为两种:一种是个人订单,一种是公司订单。现在想要实现一个通用的订单处理系统,也就是说,不管是什么类型的订单,都要能够正常处理。
## 不用模式的解决方案
```cpp
#include <iostream>
#include <memory>
#include <sstream>
#include <iostream>
#include <typeinfo>
/**
* 订单的接口,基类必须要有虚函数
*/
class OrderApi {
public:
~OrderApi() {}
virtual int getOrderProductNum() const { return orderProductNum_; }
virtual void setOrderProductNum(int num) { orderProductNum_ = num; }
virtual std::string getProductId() const { return productId_; }
virtual void setProductId(const std::string& productId) { productId_ = productId; }
private:
int orderProductNum_ = 0; // 订单产品的数量
std::string productId_; // 产品编号
};
/**
* 个人订单对象
*/
class PersonalOrder : public OrderApi {
public:
std::string getCustomerName() const { return customerName_; }
void setCustomerName(const std::string& customerName) { customerName_ = customerName; }
private:
std::string customerName_; // 订购人员姓名
std::string productId_; // 产品编号
};
/**
* 企业订单对象
*/
class EnterpriseOrder : public OrderApi {
public:
std::string getEnterpriseName() const { return enterpriseName_; }
void setEnterpriseName(const std::string& customerName) { enterpriseName_ = customerName; }
private:
std::string enterpriseName_; // 订购人员姓名
};
std::ostream& operator<<(std::ostream& os, const PersonalOrder& rhs)
{
os << "本个人订单的订单人是=" << rhs.getCustomerName() << ", 订购的产品是=" << rhs.getProductId()
<< ", 订单数量为=" << rhs.getOrderProductNum();
return os;
}
std::ostream& operator<<(std::ostream& os, const EnterpriseOrder& rhs)
{
os << "本企业订单的订购企业是=" + rhs.getEnterpriseName() << ", 订购的产品是=" << rhs.getProductId()
<< ", 订单数量为=" << rhs.getOrderProductNum();
return os;
}
std::ostream& operator<<(std::ostream& os, OrderApi* order)
{
if (typeid(*order) == typeid(PersonalOrder))
{
os << *dynamic_cast<PersonalOrder*>(order);
}
else if (typeid(order) == typeid(EnterpriseOrder))
{
os << *dynamic_cast<EnterpriseOrder*>(order);
}
return os;
}
/**
* 处理订单的业务对象
*/
class OrderBusiness {
public:
/**
* 处理订单的方法,订单的接口
*/
void saveOrder(OrderApi* order)
{
std::shared_ptr<OrderApi> newOrder = nullptr;
while (order->getOrderProductNum() > 1000)
{
if (typeid(*order) == typeid(PersonalOrder)) //基类必须有虚函数才有效
{
newOrder.reset(new PersonalOrder());
PersonalOrder* pNewOrder = dynamic_cast<PersonalOrder*>(newOrder.get());
PersonalOrder* pOrder = dynamic_cast<PersonalOrder*>(order);
pNewOrder->setCustomerName(pOrder->getCustomerName());
pNewOrder->setProductId(pOrder->getProductId());
pNewOrder->setOrderProductNum(pOrder->getOrderProductNum());
}
else if (typeid(order) == typeid(EnterpriseOrder))
{
newOrder.reset(new EnterpriseOrder());
EnterpriseOrder* pNewOrder = dynamic_cast<EnterpriseOrder*>(newOrder.get());
EnterpriseOrder* pOrder = dynamic_cast<EnterpriseOrder*>(order);
pNewOrder->setEnterpriseName(pOrder->getEnterpriseName());
pNewOrder->setProductId(pOrder->getProductId());
pNewOrder->setOrderProductNum(pOrder->getOrderProductNum());
}
std::cout << "拆分生成订单==" << newOrder.get() << std::endl;
order->setOrderProductNum(order->getOrderProductNum() - 1000);
}
std::cout << "订单==" << order << std::endl;
}
};
void test()
{
PersonalOrder personalOrder;
personalOrder.setOrderProductNum(2027);
personalOrder.setCustomerName("张三");
personalOrder.setProductId("P0001");
OrderBusiness ob;
ob.saveOrder(&personalOrder);
}
int main(int argc, char** argv)
{
test();
return 0;
}
```
运行结果:
```
拆分生成订单==本个人订单的订单人是=张三, 订购的产品是=P0001, 订单数量为=2027
拆分生成订单==本个人订单的订单人是=张三, 订购的产品是=P0001, 订单数量为=1027
订单==本个人订单的订单人是=张三, 订购的产品是=P0001, 订单数量为=27
```
上面的方法用了typeid的运行时类型判断,明显订单处理的对象依赖了订单的具体实现。这样难以扩展新的订单类型。
## 原型模式
### 原型模式定义
用原型实例指定创建对象的种类,并通过拷贝这行原型创建新的对象。
```cpp
#include <iostream>
#include <memory>
#include <sstream>
#include <iostream>
#include <typeinfo>
/**
* 订单的接口,基类必须要有虚函数
*/
class OrderApi {
public:
~OrderApi() {}
int getOrderProductNum() const { return orderProductNum_; }
void setOrderProductNum(int num) { orderProductNum_ = num; }
std::string getProductId() const { return productId_; }
void setProductId(const std::string& productId) { productId_ = productId; }
/**
* 订单原型的克隆方法
*/
virtual OrderApi* clone() = 0;
private:
int orderProductNum_ = 0; // 订单产品的数量
std::string productId_; // 产品编号
};
/**
* 个人订单对象
*/
class PersonalOrder : public OrderApi {
public:
std::string getCustomerName() const { return customerName_; }
void setCustomerName(const std::string& customerName) { customerName_ = customerName; }
virtual PersonalOrder* clone() override
{
PersonalOrder *personalOrder = new PersonalOrder();
personalOrder->setOrderProductNum(this->getOrderProductNum());
personalOrder->setProductId(this->getProductId());
personalOrder->setCustomerName(this->getCustomerName());
return personalOrder;
}
private:
std::string customerName_; // 订购人员姓名
std::string productId_; // 产品编号
};
/**
* 企业订单对象
*/
class EnterpriseOrder : public OrderApi {
public:
std::string getEnterpriseName() const { return enterpriseName_; }
void setEnterpriseName(const std::string& customerName) { enterpriseName_ = customerName; }
virtual EnterpriseOrder* clone() override
{
EnterpriseOrder *enterpriseOrder = new EnterpriseOrder();
enterpriseOrder->setOrderProductNum(this->getOrderProductNum());
enterpriseOrder->setProductId(this->getProductId());
enterpriseOrder->setEnterpriseName(this->getEnterpriseName());
return enterpriseOrder;
}
private:
std::string enterpriseName_; // 订购人员姓名
};
std::ostream& operator<<(std::ostream& os, const PersonalOrder& rhs)
{
os << "本个人订单的订单人是=" << rhs.getCustomerName() << ", 订购的产品是=" << rhs.getProductId()
<< ", 订单数量为=" << rhs.getOrderProductNum();
return os;
}
std::ostream& operator<<(std::ostream& os, const EnterpriseOrder& rhs)
{
os << "本企业订单的订购企业是=" + rhs.getEnterpriseName() << ", 订购的产品是=" << rhs.getProductId()
<< ", 订单数量为=" << rhs.getOrderProductNum();
return os;
}
std::ostream& operator<<(std::ostream& os, OrderApi* order)
{
if (typeid(*order) == typeid(PersonalOrder))
{
os << *dynamic_cast<PersonalOrder*>(order);
}
else if (typeid(order) == typeid(EnterpriseOrder))
{
os << *dynamic_cast<EnterpriseOrder*>(order);
}
return os;
}
/**
* 处理订单的业务对象
*/
class OrderBusiness {
public:
/**
* 处理订单的方法,订单的接口
*/
void saveOrder(OrderApi* order)
{
while (order->getOrderProductNum() > 1000)
{
std::shared_ptr<OrderApi> newOrder(order->clone());
newOrder->setOrderProductNum(1000);
order->setOrderProductNum(order->getOrderProductNum() - 1000);
std::cout << "拆分生成订单==" << newOrder.get() << std::endl;
}
std::cout << "订单==" << order << std::endl;
}
};
void test()
{
PersonalOrder personalOrder;
personalOrder.setOrderProductNum(2027);
personalOrder.setCustomerName("张三");
personalOrder.setProductId("P0001");
OrderBusiness ob;
ob.saveOrder(&personalOrder);
}
int main(int argc, char** argv)
{
test();
return 0;
}
```
运行结果和上面一样
## 原型模式的本质
**克隆生成对象**
- 空白目录
- 算法
- 排序
- 冒泡排序
- 选择排序
- 插入排序
- 归并排序
- 快速排序
- 计数排序
- 桶排序
- 基数排序
- 希尔排序
- 堆排序
- 二分查找
- 最小堆
- 最小索引堆
- 平衡二叉树(AVL tree)
- bitmap位图
- 布隆过滤器
- hashmap
- topK
- 跳表
- LRU Cache
- kmp
- 最小堆和堆排序
- 最短路径
- C++
- 运行时类型判断RTTI
- C++反射
- 手动实现智能指针
- 序列化实现
- rpc实现
- std::forward
- 函数指针的妙用
- C/C++
- std::function
- 同步队列
- 线程池实现
- std::promise
- 深入理解虚函数
- extern "C" 关键字讲解
- 大端小端的区别
- 简历
- 简历1
- redis
- 数据结构和对象
- sds
- list
- zskiplist
- 腾讯云redis面试题总结
- redis集群部署
- LeetCode
- 目标
- go基础
- 算法快速入门
- 数据结构篇
- 二叉树
- 链表
- 栈和队列
- 二进制
- 基础算法篇
- 二分搜索
- 排序算法
- 动态规划
- 算法思维
- 递归思维
- 滑动窗口思想
- 二叉搜索树
- 回溯法
- 其他
- 剑指offer
- 笔记
- git代理加速
- Linux
- vim大法
- vscode远程不能跳转
- cmake
- 设计模式
- 单例模式
- 简单工厂模式
- 外观模式
- 适配器模式
- 工厂方法模式
- 抽象工厂模式
- 生成器模式
- 原型模式
- 中介者模式
- 观察者模式
- 访问者模式
- 命令模式
- 网络编程
- epoll reactor模式
- linux timerfd系列函数总结
- IO
- mapreduce
- 反射器
- leo通信库
- Mutex
- Condition
- thread
- raft
- 协程
- hook
- 定时器
- 别人的面试经验
- 面试题
- vector崩溃问题
- JAVA
- Linux java环境配置
- ucore
- lab1
- FreeNOS
- leveldb
- 刷题笔记
- 回文串
- 前缀树
- 字符串查找
- 查找两个字符串a,b中的最长公共子串
- 动态规划
- golang
- 顺序循环打印实现
- 数据结构
- rpc运用
- python
- 单例
- 深拷贝浅拷贝
- 链表
- python基础题
- mysql
- 事务
- Linux
- 共享内存
- 刷题记录
- 贪心算法
- 动态规划
- 面试
- 腾讯C++面试
- 微众面试JD
- 迅雷网络面试
- 学习网址
- rabbitMq
