设计模式-牛刀小试01

news2024/11/18 9:22:56

前言

本文为datawhale2022年12月组队学习《大话设计模式》task4打卡学习,本次完成homework1。
【教程地址】https://github.com/datawhalechina/sweetalk-design-pattern

一、任务描述

1.1 背景

小李已经是一个工作一年的初级工程师了,他所在的公司是一家大型购物商场。随着各种网络购物软件兴起,老板也想做一个商场的购物 APP。分给小李的是一个一个订单结算模块,需要支持各种不同的结算策略。

1.2 需求

请帮小李写一个订单结算模块,要求支持多种结算策略:

  • 原价
  • 打 X 折
  • 满减,满 X 元减 Y 元

请注意,商品有多种类型,每种类型可能会参与不同的活动,自然需要支持不同的结算策略。

1.3 任务

共三个小任务:

  • Q1:方案设计。
  • Q2:代码实现及结果截图。
  • Q3:解释为什么要用这些模式。

1.4 要求

要求如下:

  • 输入是一揽子商品,输出是最后的订单金额。
  • 至少包含两种商品,每种使用不同的结算策略,策略可任选其中一个或两个组合(比如满减 + 打折)。
  • 不要实现具体函数或方法的逻辑,可以使用 print 输出功能。

二、任务分析

根据要求,应该采用工厂方法模式以及策略模式。具体工作如下:

  1. 首先创建抽象的费用类CashSuper和产品工厂类ProductFactory,用来分别代表不同收费策略类公共接口和具体产品的公共接口;
  2. 分别创建收费策略类CashNormalCashRebateCashReturn,继承CashSuper,用来实现相应的收费策略;
  3. 再分别创建具体产品类NormalProductFactoryRebateProductFactoryReturnProductFactory,继承于抽象类ProductFactory,在三个类中各自定义创建对应具体产品实例的方法;
  4. 创建策略模式上下文类CashContext,前端界面通过选择不同的销售策略,从而创建不同具体产品类的实例。

三、代码实现

整体上参考了策略模式案例的代码,自己在上面有所修改:

# -*- coding:utf-8 -*-
'''
@File    :   StrategyCash.py
@Time    :   2022/12/21 10:58:24
@Author  :   ziyuan
@Version :   1.0
@Contact :   1104009634@qq.com
@Desc    :   任务01订单结算模块策略模式实现
'''

# here put the import lib
import tkinter
import tkinter.ttk


# 收费的接口类
class CashSuper(object):
    def __init__(self):
        pass
    def accept_cash(self,money):
        pass

# 正常收费
class CashNormal(CashSuper):
    def accept_cash(self,money):
        return money

# 打折收费
class CashRebate(CashSuper):
    __moneyRebate = 1
    def cash_rebate(self,moneyRebateStr):
        self.__moneyRebate = float(moneyRebateStr)
    def accept_cash(self,money):
        return money*self.__moneyRebate

# 返利收费
class CashReturn(CashSuper):
    __moneyCondition = 0
    __moneyReturn = 0
    def cash_return(self,moneyConditionStr,moneyReturnStr):
        self.__moneyCondition = float(moneyConditionStr)
        self.__moneyReturn = float(moneyReturnStr)
    def accept_cash(self,money):
        result = money
        if (money >= self.__moneyCondition):
            result = money - money // self.__moneyCondition * self.__moneyReturn
        return result


# 产品的抽象类
class ProductFactory(object):
    def __init__(self,name,price):
        self.__product_name = name
        self.__product_price = price
    def set_product_name(self,name):
        self.__product_name = name
    def get_product_name(self):
        return self.__product_name
    def set_product_price(self,price):
        self.__product_price = price
    def get_product_price(self):
        return self.__product_price
    def get_cash(self):
        pass

class NormalProductFactory(ProductFactory):
    def __init__(self,name,price):
        super().__init__(name,price)
        self.cs = CashNormal()

    def get_cash(self):
        return self.cs.accept_cash(self.get_product_price())

class RebateProductFactory(ProductFactory):
    def __init__(self,name,price):
        super().__init__(name,price)
        self.cs = CashRebate()
        self.cs.cash_rebate("0.8")

    def get_cash(self):
        return self.cs.accept_cash(self.get_product_price())

class ReturnProductFactory(ProductFactory):
    def __init__(self,name,price):
        super().__init__(name,price)
        self.cs = CashReturn()
        self.cs.cash_return("300","100")

    def get_cash(self):
        return self.cs.accept_cash(self.get_product_price())


# 策略模式上下文类实现
class CashContext(object):
    def __init__(self,typ,name,price):
        if typ == "正常收费":
            self.product = NormalProductFactory(name,price)
        elif typ == "打8折":
            self.product = RebateProductFactory(name,price)
        elif typ == "满300返100":
            self.product = ReturnProductFactory(name,price)
        
    def get_result(self):
        return self.product.get_cash()

# 前端
class CashWindow(object):
    def __init__(self):
        self.total = 0
        root = tkinter.Tk()
        self.label1 = tkinter.Label(root,text="商品名称:")
        self.txtName = tkinter.Entry(root,width = 24,)
        self.label2 = tkinter.Label(root,text="商品价格:")
        self.txtPrice = tkinter.Entry(root,width = 24,)
        self.ibxList = tkinter.Text(root,width = 45, height = 10)
        self.label4 = tkinter.Label(root,text="总计:")
        
        self.iblResult = tkinter.StringVar()
        self.iblResult.set("%.2f"%self.total)
        self.result = tkinter.Label(root,textvariable=self.iblResult, height = 2, font = ('TimeNewsRoman',24))
        self.button = tkinter.Button(root,text="确定",width = 10,command = self.btnOk_click)
        self.buttonReset = tkinter.Button(root,text="重置",width = 10,command = self.btnReset_click)

        self.label3 = tkinter.Label(root,text="计算方式:")
        self.comboVar = tkinter.StringVar()
        self.combobox = tkinter.ttk.Combobox(root, textvariable = self.comboVar,width = 22,)
        self.combobox['value'] = ("正常收费","打8折","满300返100")
        self.combobox.current(0)
        self.layout()
        root.mainloop()
       
    def refresh(self):
        self.txtName.delete('0','end')
        self.txtPrice.delete('0','end')

    def layout(self):
        self.label1.grid(row = 0, column = 0, padx = (10,0), pady = 10)
        self.txtName.grid(row = 0, column = 1, pady = 10,padx = (0,5),)
        self.label2.grid(row = 1, column = 0, padx = (10,0))
        self.txtPrice.grid(row = 1, column = 1,padx = (0,5),)
        self.label3.grid(row = 2, column = 0, padx = (10,0))
        self.combobox.grid(row = 2, column = 1,padx = (0,5),pady = 10)

        self.ibxList.grid(row = 4, column = 0,columnspan = 4,padx = (5,5),pady = 10)
        self.label4.grid(row = 5, column = 0, padx = (10,0))
        self.result.grid(row = 5, column = 1,columnspan = 3, rowspan = 2)
        self.button.grid(row = 0, column = 2, columnspan = 2,pady = 10,  padx = (0,10))
        self.buttonReset.grid(row = 1, column = 2, columnspan = 2, padx = (0,10))

    def btnReset_click(self):
        self.total = 0
        self.ibxList.delete('1.0','end')
        self.iblResult.set("%.2f"%self.total)
        self.refresh()

    # 主要部分
    def btnOk_click(self):
        csuper = CashContext(self.comboVar.get(),self.txtName.get(),float(self.txtPrice.get()))
        totalPrice = float(csuper.get_result())
        self.total = self.total + totalPrice
        self.ibxList.insert('end',"商品名称:"+self.txtName.get()+
                                ",商品价格:" +self.txtPrice.get()+
                                ",销售策略:"+self.comboVar.get()+
                                "。合计:%.2f"%(totalPrice)+"\n")
        self.iblResult.set("%.2f"%self.total)
        self.refresh()

if __name__ == '__main__':
    CashWindow()

最终效果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/107289.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

靶机练习——vulnstack1

下载地址:http://vulnstack.qiyuanxuetang.net/vuln/detail/2/ 注意事项 密码一定要设置为不同的 部署环境 根据红日安全出具的wp,我们只需要设置两个C段即可,分别是外网的72和内网的52,这里直接添加新的网络以及子网地址即可&…

十三、DockerFile构建增强版本centos7

1、概述 在Docker 常用命令篇中,我们已经知道了2中构建镜像的方式 export\import 和 commit方式。这两种方式都需要先运行并创建容器,然后在容器中安装vim、ifconfig等命令,然后再重新构建加强版的镜像,比较麻烦。Dockerfile通过…

2022CTF培训(九)MIPS PWN环境搭建MIPS PWN入门

附件下载链接 环境搭建 在 ARM PWN 环境搭建 的基础上,首先安装具备MIPS交叉编译gcc与MIPS程序动态链接库: sudo apt-get install gcc-mips-linux-gnu sudo apt-get install gcc-mipsel-linux-gnu sudo apt-get install gcc-mips64-linux-gnuabi64 su…

【CANN训练营第三季】Ascend平台体验Pytorch笔记

模型迁移 手册地址:https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/600alpha002/ptmoddevg/ptmigr/ptmigr_000009.html 主要修改: 导入相关库 import torch import torch_npu #1.8.1及以上需要指定NPU设备 通过device()指定 …

JDBC编程步骤、JDBC API详解和数据库连接池

前言: JDBC 就是使用Java语言操作关系型数据库的一套API ,全称:( Java DataBase Connectivity ) Java 数据库连接。官方(sun公司)定义的一套操作所有关系型数据库的规则,即 接口各个数据库厂商去实现这套…

工具及方法 - Process Explorer以及类似工具,用来获取系统运行的进程信息

下载Process explorer: Process Explorer - Sysinternals | Microsoft Learn Process explorer简介 有没有想过哪个程序打开了一个特定的文件或目录?现在你可以找到了。Process Explorer向你显示关于进程打开或加载的句柄和DLL的信息。 Process Explore…

[Python图像处理] 使用 HSV 色彩空间检测病毒对象

使用 HSV 色彩空间检测病毒对象前言检测病毒对象相关链接前言 在本节中,我们将学习如何使用 OpenCV 在 HSV 色彩空间中使用特定颜色检测感兴趣对象。我们需要通过指定颜色值范围识别和提取感兴趣的对象,使用具有病毒的血细胞图像,我们的目标…

Python 自动化测试(五): Pytest 结合 Allure 生成测试报告

本文节选自霍格沃玆测试学院测试开发内部教材,进阶学习文末加群! 测试报告在项目中是至关重要的角色,一个好的测试报告: 可以体现测试人员的工作量; 开发人员可以从测试报告中了解缺陷的情况; 测试经理可…

7.Linux实用操作(2)

文章目录零、学习目标一、进程管理1、概念2、查看进程3、查看指定进程4、关闭进程二、主机状态1、查看系统资源占用2、top命令内容详解3、top命令选项4、top交互式选项5、磁盘信息监控三、上传、下载1、上传、下载2、rz、sz命令四、压缩、解压1、压缩格式3、tar命令4、tar 命令…

后端开发浅学react

博客笔记来自于学习 柴柴老师在b站分享的react学习视频,仅供学习参考,学习视频是来自于b站的:柴柴_前端教书匠,视频链接:React入门到实战(2022全网最新)_哔哩哔哩_bilibili 和 react官网 开始 – React …

谁会嫌钱多啊,最适合学生党的Python兼职攻略以及接私活经验

大家好,我是小八 这次我想谈谈一个非常热门的话题,就是如何在学习python的同时去赚钱。在这篇文章中,你会学习到如何通过学习python来赚取副业收入。 相信大家都对钱感兴趣吧,如果你和马云爸爸对钱不敢兴趣的话,那这…

Lambda表达式从用到底层原理

文章目录前言一、lambda函数基本使用参数列表返回类型函数体捕获列表值捕获引用捕获隐式捕获混合方式捕获修改值捕获变量的值异常说明二、lambda表达式使用的注意事项避免默认捕获模式三、lambda表达式底层实现原理采用值捕获采用引用捕获前言 lambda式作为一种创建函数对象的…

Python tkinter -- 第18章 画布控件之多边形

18.2.19 create_polygon(coords, **options) 根据 coords 给定的坐标,在画布上绘制一个多边形。 (1)coords:给定多边形的坐标 (2)options:选项的具体含义: 选项含义activedash当鼠标…

JavaEE- JVM八股文(JVM垃圾回收机制GC)

JVM垃圾回收的目标:主要针对内存中的堆空间进行垃圾回收。 Java中,大量的内存都在堆中。 程序计数器:固定大小,不涉及释放 栈:函数执行完毕,对应栈的空间就自动释放了,不需要垃圾回收 方法区&…

07-Golang中标识符的命名规则

Golang中标识符的命名规则标识符概念标识符的命名规则保留关键字介绍预定义标识符介绍标识符命名注意事项标识符概念 1.Golang对各种变量、方法等命名时使用的字符序列称为标识符 2.凡是自己可以起名字的地方都叫标识符 标识符的命名规则 1.由26个英文字母大小写&#xff0…

华为云桌面之下的“冰山”:技术底座x繁荣生态加速模式进化

在新兴技术迭代升级持续加速的背景下,很多产品类别的内涵和外延都在不断演进——虽然名字没什么变化,但实际所指已有云泥之别。 “云桌面”即是如此。从早期的无盘工作站,到VDI、IDV和VOI等技术流派的群雄并起,云桌面的江湖总是“…

linux第七章---管道、环境变量、常用命令

1.管道 1.1概念: 管道类似于文件重定向,可以将前一个命令的stdout重定向到下一个命令的stdin。 1.2要点: 管道命令仅处理stdout,会忽略stdeer。管道右边的命令必须要能接受stdin.多个管道命令可以串联。 1.3与文件重定向的区…

Java平衡树之查找树的详解(1)

1.平衡树 之前我们学习过二叉查找树,发现它的查询效率比单纯的链表和数组的查询效率要高很多,大部分情况下,确实是这样的,但不幸的是,在最坏情况下,二叉查找树的性能还是很糟糕。例如我们依次往二叉查找树中…

c语言预处理(万字解析)

预处理一.总体概述1.注释去除2.宏替换二.宏定义(宏替换类型)1.数值宏常量2.字符串宏常量3.用宏定义注释符号4.用宏定义表达式(难点)1.第一种情况2.第二种情况5.#undef(宏的有效范围)1.两个问题2.#undef的使…

FLStudio2023水果软件哪个版本好用?功能区别对比

FL Studio是一款功能非常强大的音乐创作编辑软件它就是FL Studio(水果软件)。使用FL Studio中文版可以轻松帮我们制作自己的音乐唱片,拥有强大且专业的编曲混音创作工具,有需要的朋友不要错过。 水果,全称Fruity Loop Studio,简称…