内容要求

在这边把两次作业合在一起。作业要求实现一个商场结算程序。其中要完成几个功能:

  1. 结算模块。针对不同的商品不同的营销策略(不同打折方式)进行结算;
  2. 商品状态。商品需要至少包含在售缺货以及上架中等三种状态;
  3. 商品上架审核功能。

针对这三个功能,我将程序拆开成三个部分看待:商品模块,结算模块,审核模块。

商品模块

设计商品基类。在这里我打算设计成单例模式。因此商品类别是独一份的,这样有个好处就是商品的价格一直是统一的,并不会因为新创建了新的对象而导致出现同一类商品出现不同价格的情况。

class Product {
public:virtual double GetPrice() = 0; virtual void SetPrice(double price) = 0;virtual void SetState(State *state) = 0;virtual bool isOnSale() = 0;virtual ProductKey GetName() = 0;virtual void ShowState() = 0;
};

基于基类,创建子类 Pen, Suit 以及 Book。以下只放出来 Pen 类。

class Pen : public Product {
private:State             *state_;double            price_;ProductKey        name_;static Pen        *instance_;static std::mutex mutex;Pen();public:static Pen *GetInstance(); double GetPrice(); void SetPrice(double price);void SetState(State *state);bool isOnSale();ProductKey GetName();void ShowState();
};

同时题目中有提到至少有三种状态,因此考虑到之后可能新增状态,这边把状态也当作一个类别,作为商品的一个属性。

class State {
public:virtual void writeState(Product *p) = 0;virtual bool isAvaible() = 0;
};class onSale : public State {
public:void writeState(Product *p) override;bool isAvaible() override;};class outOfStock : public State {
public:void writeState(Product *p) override;bool isAvaible() override;
};class waitting : public State {
public:void writeState(Product *p) override;bool isAvaible() override;
};

而为了将商品实现细节对外隐藏,这边尝试新建了 ProductList 类别,用来作为与外界的接口。这样之后新增商品就不需要动到其他模块。这边的应用应该算是策略模式吧。

class ProductList {
private:std::map<std::string, ProductKey> list_ = {{"Pen", PEN},{"Suit",SUIT},{"Book", BOOK},};
public:ProductList(){};ProductKey GetProductKey(std::string p_name);Product *GetInstance(std::string p_name);double GetPrice(std::string p_name);void SetPrice(std::string p_name, double price);void SetState(std::string p_name, std::string state);bool isOnSale(std::string p_name);void ShowState(std::string);
};

结算模块

在结算模块中,本程序使用了策略方式模式。创建了三种营销方式,分别是普通(Normal),打折(Rebate)以及返利(Return)。

class StrategyBase {
public:virtual double acceptCash(double money) const = 0;
};class StrategyNormal : public StrategyBase {
public:double acceptCash(double money) const override;
};class StrategyRebate : public StrategyBase {
private:double money_rebate_ = 1.0;
public:explicit StrategyRebate(double money_rebate);double acceptCash(double money) const override;
};class StrategyReturn : public StrategyBase {
private:double money_contion_ = 0.0;double money_return_ = 0.0;
public:explicit StrategyReturn(double money_contion, double money_return);double acceptCash(double money) const override;
};

但此时还存在一个问题,就是每个商品的营销策略可能不同,我们当前还没维护商品的营销策略。在此我为了尽可能不修改已有的代码,对每个商品的营销策略进行了维护。

class ProduceStrategy {
private:std::map<ProductKey, StrategyKey> mp = {{PEN, moneyRebate_008},{SUIT, moneyReturn_10_1},{BOOK, moneyNormal},};static ProduceStrategy *instance_;ProduceStrategy() = default;
public:static ProduceStrategy *GetInstance();StrategyKey GetStrategy(ProductKey pk);void Update(ProductKey pk, StrategyKey sk);
};

这样当之后商品的营销策略发生改变之后,我们也能使用 ProduceStrategy 类进行维护更新。同时为了营销策略的唯一,这边使用了单例模式。

class CashAll {
private:ProduceStrategy *ps_;ProductList *pl_;
public:CashAll(ProduceStrategy *ps, ProductList *pl);double acceptCash(std::vector<std::string> prods);
};

之后根据策略以及商品属性,我们计算需要收的金额。

审核模块

在审核模块中,这边使用了职责链模式。需要设计请求类别以及管理者类别。

请求类别如下

class RequstStocking {
private:Product *pd_;
public:RequstStocking(Product *pd);void SetProduct(Product *pd);void finish();
};

设计进货上架审核要经过仓库中心(ProCenter),售卖中心(SaleCenter)以及总理(Manager)审核。这三类都继承于管理者(Manager)

class Manager {
protected:Manager *superior_;
public:Manager();void SetSuperior(Manager *superior);virtual void RequstApplications(RequstStocking *req) = 0;
};class ProCenter : public Manager {
public:ProCenter();void RequstApplications(RequstStocking *req) override;
};class SaleCenter : public Manager {
public:SaleCenter();void RequstApplications(RequstStocking *req) override;
};class CommonManager : public Manager {
public:CommonManager();void RequstApplications(RequstStocking *req) override;
};

结果

为了更方便检测代码,这边将各个模块分开测试。

商品模块

int main() {ProductList *list_p = new ProductList;list_p->ShowState("Pen");if (list_p->isOnSale("Pen")) std::cout << "Pen is on sale" << std::endl;list_p->SetState("Pen", "缺货");list_p->ShowState("Pen");if (list_p->isOnSale("Pen") == false)std::cout << "Pen is not on sale" << std::endl;std::cout << "Pen price : " << list_p->GetPrice("Pen") << std::endl;return 0;
}

![[image-20221230175556952.png]]

结算模块

int main() {std::vector<std::string> list_p;list_p.push_back("Pen");list_p.push_back("Book")ProduceStrategy *ps = ProduceStrategy::GetInstance();std::cout << ps->GetStrategy(PEN) << std::endl;ProductList *pl = new ProductList;CashAll *ca = new CashAll(ps, pl);std::cout << ca->acceptCash(list_p) << std::endl;return 0;
}

![[image-20221230180011043.png]]

这边的 Pen 原价 10,打8折;Book 原价 15.5,没参与活动。

审核模块

int main() {Product *p = Pen::GetInstance();RequstStocking *req = new RequstStocking(p);p->ShowState();ProCenter *pc = new ProCenter;SaleCenter *sc = new SaleCenter;CommonManager *cm = new CommonManager;pc->SetSuperior(sc);sc->SetSuperior(cm);pc->RequstApplications(req);p->ShowState();return 0;
}

![[image-20221230180358924.png]]

PS:考虑到具体实现放上来会比较乱,同时最近比较忙,等整理完之后会将代码交互等地方整理好之后再上传。

在这次学习中,收获还是挺大的。由于本身是做 AI 方向的研究,对于代码的工程化能力较差。本次通过学习并且通过大作业将设计模式大体梳理了下,对于程序的结构有了更加清晰的认识。果然 talk is cheap, show me the code。

Reference

  1. Github: sweetalk-design-pattern
  2. 《大话设计模式》解读
  3. 《大话设计模式》

「大话设计模式 - 解读」5 大作业相关推荐

  1. 「大话设计模式 - 解读」0 设计原则

    看到 Datawhale 的推送之后,也刚好借此时间阅读下设计模式,提升下代码能力.本次学习主要针对面向对象语言,在此选用 C++ 进行学习,参考学习资料: Github: sweetalk-desi ...

  2. 「大话设计模式 - 解读」1 策略、修饰、代理模式

    策略模式 在日常中,我们常随着时间的不同对同一件事的处理会发生不同.就好像一件物品,在购物平台上的销售策略会发生变化,时而打折,时而满xx元返xx元.这些都是不同的策略,然后策略是无法穷尽的,他们都有 ...

  3. 「TCG 规范解读」初识嵌入式和工业工作组

    可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性.TCG于2003年春成立,并采纳了由可信计算平台 ...

  4. 「TCG 规范解读」初识基础设施工作组

    可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性.TCG于2003年春成立,并采纳了由可信计算平台 ...

  5. 「专治不明觉厉」之“大数据”

    大数据(Big Data) 大数据,官方定义是指那些数据量特别大.数据类别特别复杂的数据集,这种数据集无法用传统的数据库进行存储,管理和处理.大数据的主要特点为数据量大(Volume),数据类别复杂( ...

  6. 「TCG 规范解读」初识云和 DICE 工作组

    可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性.TCG于2003年春成立,并采纳了由可信计算平台 ...

  7. 83.76%任职回报!这位「互联网研霸」基金经理的作业赶快抄!

    文|螳螂财经 ​作者| 易不二 "只要不是过于急于求成,合理投资能使你非常富有."--巴菲特 全民养"基"时代来临 2021年春节后的行情波动,把基金带上了四次 ...

  8. 「源码解读」知名程序员 TJ 的 only 库

    大家好,我是前端西瓜哥.我最近尝试开启一个源码解读系列,不定期解读一些简单或复杂的源码. 今天要解读 npm 第三方库的源码:only,仓库地址为:https://github.com/tj/node ...

  9. 前端H5怎么切换语言_「自学系列一」HTML5大前端学习路线+视频教程完整版

    全新Java.HTML5前端.大数据.Python爬虫.全链UI设计.软件测试.Unity 3D.Go语言等多个技术方向的全套视频. 面对这么多的知识点,有的盆友就麻爪了-- 我是谁? 我该从哪里开始 ...

最新文章

  1. ERROR: Failed to resolve: com.android.support:appcompat-v7:29.0.0
  2. 怎样用c语言解一元一次方程,问一道算法题目(解一元一次方程的问题)
  3. 互次方科技金立(沃兹):深入浅出项目管理
  4. python计算生态的命名_Python计算生态之random库
  5. python实现多进程同时计算_python多进程实现CPU100%使用
  6. 当电桥为恒流源时惠斯通电桥电压的计算方法
  7. 时间模块,带Python示例
  8. python获取网页数据对电脑性能_【Python】网页数据爬取实战
  9. 作为现代行业才有的程序员为何地位不高?
  10. c++ 记忆化搜索_2010/12区间动态规划及记忆化搜索
  11. GIT上传代码Enumerating objects:类型报错解决,实测可用
  12. 用Prettier和ESlint来统一提交代码
  13. 这只拒绝内卷的 AI 狼火了!高智商却自暴自弃,不想抓羊只想躺
  14. MATLAB画图详细教程
  15. win7 64位系统加载dsoframer.ocx问题解决方法
  16. 一键获取网页中的全部图片并批量下载(国内淘宝天猫京东网站+国外商品页面)——亲测有效
  17. SSIS(数据流任务)
  18. (1)JfreeChart之柱状图
  19. 工程师笔记|STM32U5带OEM Key保护的RDP降级
  20. 20 多个国外优秀Android开源 App ,值得收藏和学习

热门文章

  1. git修改密码后,不能push或者pull问题
  2. 在江湖混要养成的10个好习惯
  3. C# 数据库通用类
  4. MyBatis查询结果resultType
  5. win7 计算机登录用户密码,win7系统忘记密码后强制登录系统的方法
  6. 非常实用的移动web开发资源整理
  7. cfg桩设备型号_湖北CFG桩机型号规格齐全
  8. Css 兼容IE+,FF
  9. 网站设计和平面设计区别_平面网站设计终极指南
  10. iOS DrawRect简单使用