【大话设计模式】工厂+策略+装饰模式 hw01

news2024/11/15 21:38:58

背景

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

需求

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

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

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

任务

共三个小任务:

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

要求

要求如下:

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

================================

类图

 

客户端:

import java.lang.reflect.Array;
import java.util.*;

public class Main {
    public static void main(String[] args) {


        double price = 0d;
        double totalPrice = 0d;
        double total = 0d;
        int strategy = 0;
        int num = 0;
        Scanner scanner = new Scanner(System.in);
        Integer goodCount=0;
        Integer tag = 1;
        String goods = "";


        do{
            System.out.println("---------------二、请输入商品销售模式 1.原价 2.八折 3.满300返100 4.先打8折,再满300返100 5. 先满200返50,再打7折 ---------------");
            strategy = Integer.parseInt(scanner.nextLine());
            System.out.println("---------------请输入商品单价:---------------");
            price = Double.parseDouble(scanner.nextLine());
            System.out.println("---------------请输入商品数量:---------------");
            num = Integer.parseInt(scanner.nextLine());
            System.out.println();

            if(price >0 && num>0){

                //这里就可以去写一个工厂
//                CashSuper oper = CashFactory.createCrash(discount);
//                totalPrice = oper.getCrash(price,num);

                CashContext cc = new CashContext(strategy);
                totalPrice = cc.getResult(price,num);
                total = total + totalPrice;

                System.out.println();
                System.out.println("单价:" + price + "元 数量:" + num + " 合计:" + totalPrice + "元");
                System.out.println();
                System.out.println("总计:" + total + "元");
                System.out.println();
            }

            goodCount++;
            if(goodCount>=2){
                System.out.println("是否退出?0-退出");
                tag = Integer.parseInt(scanner.nextLine());
            }

        }while(goodCount<2 && tag>0);

        System.out.println("感谢使用!");
    }
}

 CashContext:

public class CashContext {

    private ISale cs;

    public CashContext(int cashSuper){
//        this.cs = cashSuper;

//        CashSuper oper = null;
        switch (cashSuper){
            case 1:
                this.cs = new CashNormal();
                break;
            case 2:
                this.cs = new CashRebate(0.8d);
                break;
            case 3:
                this.cs = new CashReturn(300d,100d);
            case 4:
                // 先打8折,再满300返100
                CashNormal cn = new CashNormal();
                CashReturn cr1 = new CashReturn(300d,100d);
                CashRebate cr2 = new CashRebate(0.8d);

                cr1.decorate(cn);
                cr2.decorate(cr1);

                this.cs = cr2;
                break;
            case 5:
                //先满200返50,再打7折
                CashNormal cn2 = new CashNormal();
                CashRebate cr3 = new CashRebate(0.7d);
                CashReturn cr4 = new CashReturn(200d,50d);
                cr3.decorate(cn2); //用打7折算法包装基本的原价算法
                cr4.decorate(cr3); //满200返50算法装饰打7折算法
                this.cs = cr4; //将包装好的算法组合引用传递给cs对象
                break;
        }

    }

    public double getResult(double price,int num){
        return this.cs.getCrash(price,num);
    }
}

原价、打折、满减

public class CashNormal implements ISale {
    public double getCrash(double price,int num){
        return price * num;
    }
}
public class CashRebate extends CashSuper {

    private double moneyRebate = 1d;

    public CashRebate(double moneyRebate){
        this.moneyRebate = moneyRebate;
    }

    public double getCrash(double price,int num){
        double result =  price * num * this.moneyRebate;
        return super.getCrash(result,1);
    }

}


public class CashReturn extends CashSuper {

    private double moneyReturn = 0d;
    private double moneyCondition = 0d;

    public CashReturn(double moneyCondition,double moneyReturn){
        this.moneyReturn = moneyReturn;
        this.moneyCondition = moneyCondition;
    }

    public double getCrash(double price,int num){
        double result = price * num;
        if (moneyCondition>0 && result >= moneyCondition){
            result = result - Math.floor(result/moneyCondition) * moneyReturn;
        }
        return super.getCrash(result,1);
    }

}

定义装饰方法

public class CashSuper implements ISale{

    protected ISale component;

    public void decorate(ISale component){
        this.component = component;
    }

    public double getCrash(double price,int num){
        double result = 0d;
        if(this.component != null){
            result = this.component.getCrash(price,num);
        }
        return result;
    }

}

 接口

public interface ISale {
    public double getCrash(double price,int num);
}

 

为什么要用这些模式?

我的理解是简单工厂模式首先把业务逻辑抽离出来,主要是跟客户端的业务逻辑分离。

策略模式:仅仅比工厂模式多一个类,去选择使用哪一个模式。

装饰模式:它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了.

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

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

相关文章

vm2 <3.9.10 存在任意代码执行漏洞

漏洞描述 vm2 是一个基于 Node.js 的沙箱环境&#xff0c;可以使用列入白名单的 Node 内置模块运行不受信任的代码。 vm2 3.9.10之前版本中由于 WeakMap.prototype.set 方法使用原型查找从而存在任意代码执行漏洞&#xff0c;攻击者可利用此漏洞在沙箱内执行任意恶意代码&…

盲盒抽奖流程

盲盒模块的流程大致如下&#xff1a; 进入盲盒抽奖页面&#xff0c;需要初始化直接获取一些盲盒的信息&#xff0c;例如&#xff1a;盲盒活动id&#xff0c;开奖buff等。首先需要获取盲盒活动id&#xff0c;后面的所有请求都是基于盲盒活动id进行的。 初始化获取: 盲盒活动id…

Thymeleaf 下拉列表传值示例

参考资料 Spring Boot で Thymeleaf 使い方メモ 目录一. 前期准备二. 实体类.内部类设置下拉列表值2.1 form实体类2.2 Controller层2.3 Thymeleaf页面三. request.setAttribute()设置下拉列表值3.1 定义下拉列表存放类3.2 Controller层3.3 Thymeleaf页面一. 前期准备 枚举类 …

FT2232作为JTAG烧录器的使用步骤详解

FT2232作为JTAG烧录器的使用步骤详解FT2232作为JTAG烧录器的使用步骤详解配置OpenOCD环境(已经配置好的可以跳过)【步骤 1】安装 FT2232HL 芯片的驱动&#xff0c;安装文件为 CDM21228_Setup.exe。【步骤 2】 安装 FT_Prog_v3.6.88.402 Installer.exe【步骤 3】 使用 FT Prog 软…

模型实战一之YOLOv7实例分割、模型寻来自己数据集

模型实战一之YOLOv7实例分割、模型训练自己数据集 1.环境准备 下载yolov7实例分割模型&#xff1a; git clone https://github.com/WongKinYiu/yolov7.git -b mask yolov7-maskcd yolov7-mask安装环境 #查看已安装环境 conda info --envs #查看安装了哪些包 conda list#创建…

神奇的线性表(链表)

目录 神马是链表 链表的分类 单向链表 链表的常用操作 查找操作 插入操作 删除操作 链表与数组 数组的插入 数组的删除 链表的应用 尾声 神马是链表 记得很久很久以前…我们学习过数组&#xff0c; 数组是在内存中一段连续的存储空间&#xff0c; 可以在常数时间内访…

逻辑分析仪解析SPI数据

工具为梦源逻辑分析仪&#xff0c;本次测试的是ST7789v屏幕驱动 接线方面一共需要三根线&#xff08;MOSI&#xff0c;SCL&#xff0c;GND&#xff09; SCL PA5 MOSI PA7 DSView上位机配置 通道按照接线选择&#xff0c;这个一定要对应上 COPL CPOH按照SPI实际配置来&#x…

生成模型(四):扩散模型(Diffusion Models)

本文大纲如下&#xff1a; 生成模型种类 到目前为止&#xff0c;我已经写了三种类型的生成模型&#xff0c;[[生成模型-GAN]]、[[生成模型-VAE]]和[[生成模型-Flow based model]]。 它们在生成高质量样本方面显示出巨大的成功&#xff0c;但每一种都有其自身的一些局限性。下…

基于Python的GUI图形用户界面编程

【无限嚣张&#xff08;菜菜&#xff09;】&#xff1a;hello您好&#xff0c;我是菜菜&#xff0c;很高兴您能来访我的博客&#xff0c;我是一名爱好编程学习研究的菜菜&#xff0c;每天分享自己的学习&#xff0c;想法&#xff0c;博客来源与自己的学习项目以及编程中遇到问题…

非零基础自学Golang 第17章 HTTP编程(上) 17.2 HTTP客户端 17.2.4 发起POST请求

非零基础自学Golang 文章目录非零基础自学Golang第17章 HTTP编程(上)17.2 HTTP客户端17.2.4 发起POST请求第17章 HTTP编程(上) 17.2 HTTP客户端 17.2.4 发起POST请求 在上一小节我们使用了http.NewRequest来创建一个请求&#xff0c;http.NewRequest有三个参数&#xff0c;第…

web前端-javascript-String字符串的相关方法

文章目录字符串的相关方法1. 底层字符串保存2. 方法1) length 属性 获取长度2) charAt() 获取指定字符3) chartCodeAt() 获取指定字符编码4) String.formCharCode() 根据编码获取字符5) concat() 连接字符串6) indexOf() 是否含有指定内容7) lastIndexOf() 是否含有指定内容8) …

哈斯机床联网

一、设备信息确认 1、确认型号 哈斯的数控面板共有两种情况。 老版本&#xff1a; 新版本&#xff1a; 注&#xff1a;老版本通讯为串口&#xff0c;新版本通讯为网口。 2、确认通讯接口 1、数控面板的后面 老版本的串口一般都会引出在正后面的左侧位置&#xff0c;上面有…

结构型模式之代理模式(八)

常说的设计模式是23种设计模式&#xff0c;分为3大类&#xff1a; 创建型模式5种&#xff1a;工厂方法、抽象工厂、单例、建造者、原型结构型模式7种&#xff1a;适配器、代理、桥接、装饰者、外观、享元、组合行为型模式11种&#xff1a;模板方法、解释器、策略、观察者、迭代…

非零基础自学Golang 第15章 Go命令行工具 15.5 代码测试(test) 15.5.1 单元测试

非零基础自学Golang 文章目录非零基础自学Golang第15章 Go命令行工具15.5 代码测试(test)15.5.1 单元测试第15章 Go命令行工具 15.5 代码测试(test) go test命令用于对Go语言编写的代码包进行测试。 可以指定要测试的文件&#xff0c;也可以直接对整个包进行测试&#xff0c…

[Java实战]Squaretest单元测试生成利器...一天生成所有简单单元测试...[新手开箱可用]

Squaretest单元测试生成利器...一天生成所有简单单元测试...[新手开箱可用]1.Squaretest是什么?2.如何配合JUnit使用...?3.生成的java文件长啥样?4.如何生成和使用?5.如何用生成的XXXTest.java文件进行单元测试...6.观察结果7.单元测试成功8.源码地址为了好好写单元测试,提…

Dell inspiron 7580硬件升级_更换电池加内存条移动硬盘

文章目录前言硬件升级确认硬件型号参数拆机验证硬件更新后记前言 手上的笔记本[Dell inspiron 7580]用了几年了&#xff0c;还是刚上大学的时候买的&#xff0c;现在感觉这个配置用起来有点吃力了&#xff0c;稍微更新一下配置准备再战两年┭┮﹏┭┮ Light em up, light em u…

参数扫描文件的用法

摘要 通过控制和改变所选参数有助于检查给定光学系统的性能。 VirtualLab Fusion提供了完全灵活且计算效率高&#xff08;通过并行化&#xff09;的参数运行&#xff0c;使用户可以指定不同的参数变化方式。 作为示例&#xff0c;它可以用于所研究的任何系统参数的公差分析。 分…

Moonbeam生态说|Moonbeam Ignite重燃DeFi生态活力

日前&#xff0c;Moonbeam Network生态中两家活跃度最高的DeFi协议Moonwell和StellaSwap受邀参加Moonbeam中文社区BinanceLive直播。 作为Moonbeam生态的老朋友&#xff0c;两家项目方的联合创始人对赋能生态胸有成竹。 今年11月&#xff0c;Moonwell和StellaSwap都得到社区投票…

MORE CONVNETS IN THE 2020S: SCALING UP KER- NELS BEYOND 51 × 51 USING SPARSITY

论文链接: https://arxiv.org/pdf/2207.03620.pdf code: https://github.com/VITA-Group/SLaKlink MORE CONVNETS IN THE 2020S: SCALING UP KER- NELS BEYOND 51 51 USING SPARSITY一、引言&#xff08;二&#xff09;、大内核注意力&#xff08;二&#xff09;、卷积中的大…

I/O多路转接 —— select、poll、epoll

目录 一、概述 二、I/O多路转接 —— select 1. select函数的基本介绍 2. select的基本工作流程 3. 文件描述符的就绪条件 4. 基于select函数设计的服务器 1. 基本套接字的编写 2. select服务器的编写 5. select的优缺点 三、I/O多路转接 —— poll 1. poll函数的基…