商场促销--策略模式

1.1 商场收银软件

package com.lhx.design.pattern.test;

import java.util.Scanner;

public class Test {

	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

		double price = 0d; 		//商品单价
		int num = 0;			//商品购买数量
		double totalPrices = 0d;//当前商品合计费用
		double total = 0d;		//总计所有商品费用
		
		Scanner sc = new Scanner(System.in);

		do {
			System.out.println("请输入商品单价:");	
			price = Double.parseDouble(sc.nextLine());
			System.out.println("请输入商品数量:");	
			num = Integer.parseInt(sc.nextLine());
			System.out.println();	

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

				totalPrices = price * num;
				total = total + totalPrices;
				
				System.out.println();	
				System.out.println("单价:"+ price + "元 	数量:"+ num +" 合计:"+ totalPrices +"元");	
				System.out.println();
				System.out.println("总计:"+ total+"元");	
				System.out.println();
			}
		}
		while(price>0 && num>0);

		System.out.println();		

		System.out.println("**********************************************");

	}
}

1.2 增加打折

1.正常收费 2.打八折 3.打七折
package com.lhx.design.pattern.test;

import java.util.Scanner;

public class Test {

	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

		int discount = 0; 		//商品折扣模式(1.正常收费 2.打八折 3.打七折)
		
		double price = 0d; 		//商品单价
		int num = 0;			//商品购买数量
		double totalPrices = 0d;//当前商品合计费用
		double total = 0d;		//总计所有商品费用
		
		Scanner sc = new Scanner(System.in);

		do {
			System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折):");	
			discount = Integer.parseInt(sc.nextLine());
			System.out.println("请输入商品单价:");	
			price = Double.parseDouble(sc.nextLine());
			System.out.println("请输入商品数量:");	
			num = Integer.parseInt(sc.nextLine());
			System.out.println();	

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

				switch(discount){
					case 1:
						totalPrices = price * num;
						break;
					case 2:
						totalPrices = price * num * 0.8;
						break;
					case 3:
						totalPrices = price * num * 0.7;
						break;
				}
				
				total = total + totalPrices;
				
				System.out.println();	
				System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");	
				System.out.println();
				System.out.println("总计:"+ total+"元");	
				System.out.println();
			}
		}
		while(price>0 && num>0);

		System.out.println();		

		System.out.println("**********************************************");

	}
}

1.3 简单工厂实现

商场的活动加大,需要有满300返回100的促销算法,又增加是700就要返200呢?或者说需要现在打三折,又要满300送80呢?

收费抽象类

package com.lhx.design.pattern.test;
//收费抽象类
public abstract class CashSuper {

    //收取费用的抽象方法,参数为单价和数量
    public abstract double acceptCash(double price,int num);
    
}
package com.lhx.design.pattern.test;

public class CashNormal extends CashSuper {

    //正常收费,原价返回
    public double acceptCash(double price,int num){
        return price * num;
    }
    
}
package com.lhx.design.pattern.test;

public class CashRebate extends CashSuper {

    private double moneyRebate = 1d;
    //打折收费。初始化时必需输入折扣率。八折就输入0.8
    public CashRebate(double moneyRebate){
        this.moneyRebate = moneyRebate;
    }

    //计算收费时需要在原价基础上乘以折扣率
    public double acceptCash(double price,int num){
        return price * num * this.moneyRebate;
    }
    
}
package com.lhx.design.pattern.test;

public class CashReturn extends CashSuper {

    private double moneyCondition = 0d; //返利条件
    private double moneyReturn = 0d;    //返利值

    //返利收费。初始化时需要输入返利条件和返利值。
    //比如“满300返100”,就是moneyCondition=300,moneyReturn=100
    public CashReturn(double moneyCondition,double moneyReturn){
        this.moneyCondition = moneyCondition;
        this.moneyReturn = moneyReturn;
    }

    //计算收费时,当达到返利条件,就原价减去返利值
    public double acceptCash(double price,int num){
        double result = price * num;
        if (moneyCondition>0 && result >= moneyCondition)
            result = result - Math.floor(result / moneyCondition) * moneyReturn; 
        return result;
    }
    
}
package com.lhx.design.pattern.test;

public class CashFactory {

    //收费工厂
    public static CashSuper createCashAccept(int cashType){
        CashSuper cs = null;
        switch (cashType) {
            case 1:
                cs = new CashNormal();      //正常收费
                break;
            case 2:
                cs = new CashRebate(0.8d);  //打八折
                break;
            case 3:
                cs = new CashRebate(0.7d);  //打七折
                break;
            case 4:
                cs = new CashReturn(300d,100d);//满300返100
                break;

        }
        return cs;
    }
    
}

package com.lhx.design.pattern.test;

import java.util.Scanner;

public class Test {

	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

		int discount = 0; 		//商品折扣模式(1.正常收费 2.打八折 3.打七折)
		
		double price = 0d; 		//商品单价
		int num = 0;			//商品购买数量
		double totalPrices = 0d;//当前商品合计费用
		double total = 0d;		//总计所有商品费用
	
		Scanner sc = new Scanner(System.in);

		do {
			System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折 4.满300送100):");	
			discount = Integer.parseInt(sc.nextLine());
			System.out.println("请输入商品单价:");	
			price = Double.parseDouble(sc.nextLine());
			System.out.println("请输入商品数量:");	
			num = Integer.parseInt(sc.nextLine());
			System.out.println();	

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

				//简单工厂模式根据discount的数字选择合适的收费类生成实例
				CashSuper csuper = CashFactory.createCashAccept(discount);
				//通过多态,可以根据不同收费策略计算得到收费的结果
				totalPrices = csuper.acceptCash(price,num);
				
				total = total + totalPrices;
				
				System.out.println();	
				System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");	
				System.out.println();
				System.out.println("总计:"+ total+"元");	
				System.out.println();
			}
		}
		while(price>0 && num>0);

		System.out.println();
		System.out.println("**********************************************");

	}
}

1.4 策略模式

        我要是需要打五折和满500送200的促销活动,只要在现金工厂当中加两个条件,就okl ,准确的来说是收费对象生产工厂才正确,如果我现在需要增加一种商场促销手段,满100积分10点,以后到一定时候可以领取奖品如何做?

        "有了工厂,何难?加一个积分算法,构造方法有两个参数:条件和返点,让它继承CashSuper,再到现金工厂,哦,不对,是收费对象生成工厂里增加满100积分10点的分支条件,再到界面稍加改动,就行了。"

        简单工厂模式虽然也能解决这个问题,但这个模式只是解决对象的创建问题,而且由于工厂本身包括所有的收费方式,商场是可能经常性地更改打折额度和返利额度,每次维护或扩展收费方式都要改动这个工厂,以致代码需重新编译部署,这真的是很糟糕的处理方式,所以用它不是最好的办法。面对算法的时常变动,应该有更好的办法。好好去研究一下其他的设计模式,你会找到答案的。

策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。

Strategy类,定义所有支持的算法的公共接口:

Context类,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用。

客户端代码:

1.5 策略模式实现

package com.lhx.design.pattern.test;

public class CashContext {

    private CashSuper cs;   //声明一个CashSuper对象

    //通过构造方法,传入具体的收费策略
    public CashContext(CashSuper csuper){
        this.cs = csuper;
    }

    public double getResult(double price,int num){
        //根据收费策略的不同,获得计算结果
        return this.cs.acceptCash(price,num);
    }    
}
package com.lhx.design.pattern.test;

import java.util.Scanner;

public class Test {

	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

		int discount = 0; 		//商品折扣模式(1.正常收费 2.打八折 3.打七折)
		
		double price = 0d; 		//商品单价
		int num = 0;			//商品购买数量
		double totalPrices = 0d;//当前商品合计费用
		double total = 0d;		//总计所有商品费用
	
		Scanner sc = new Scanner(System.in);

		do {
			System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折 4.满300送100):");	
			discount = Integer.parseInt(sc.nextLine());
			System.out.println("请输入商品单价:");	
			price = Double.parseDouble(sc.nextLine());
			System.out.println("请输入商品数量:");	
			num = Integer.parseInt(sc.nextLine());
			System.out.println();	

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

				
				CashContext cc = null;

				//根据用户输入,将对应的策略对象作为参数传入CashContent对象中
				switch(discount){
		            case 1:
		                cc = new CashContext(new CashNormal());
		                break;
		            case 2:
		                cc = new CashContext(new CashRebate(0.8d));
		                break;
		            case 3:
		                cc = new CashContext(new CashRebate(0.7d));
		                break;
		            case 4:
		                cc = new CashContext(new CashReturn(300d,100d));
		                break;
		        }
				
				//通过Context的getResult方法的调用,可以得到收取费用的结果
				//让具体算法与客户进行了隔离
				totalPrices = cc.getResult(price,num);
				
				total = total + totalPrices;
				
				System.out.println();	
				System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");	
				System.out.println();
				System.out.println("总计:"+ total+"元");	
				System.out.println();
			}
		}
		while(price>0 && num>0);

		System.out.println();
		System.out.println("**********************************************");

	}
}

把这个判断过程从客户端程序移走

1.6 策略与简单工厂结合

package com.lhx.design.pattern.test;

public class CashContext {

    private CashSuper cs;   //声明一个CashSuper对象

    //通过构造方法,传入具体的收费策略
    public CashContext(int cashType){
        switch(cashType){
            case 1:
                this.cs = new CashNormal();
                break;
            case 2:
                this.cs = new CashRebate(0.8d);
                break;
            case 3:
                this.cs = new CashRebate(0.7d);
                break;
            case 4:
                this.cs = new CashReturn(300d,100d);
                break;
        }
    }

    public double getResult(double price,int num){
        //根据收费策略的不同,获得计算结果
        return this.cs.acceptCash(price,num);
    }    
}
package com.lhx.design.pattern.test;

import java.util.Scanner;

public class Test {

	public static void main(String[] args){

		System.out.println("**********************************************");		
		System.out.println("《大话设计模式》代码样例");
		System.out.println();		

		int discount = 0; 		//商品折扣模式(1.正常收费 2.打八折 3.打七折)
		
		double price = 0d; 		//商品单价
		int num = 0;			//商品购买数量
		double totalPrices = 0d;//当前商品合计费用
		double total = 0d;		//总计所有商品费用
	
		Scanner sc = new Scanner(System.in);

		do {
			System.out.println("请输入商品折扣模式(1.正常收费 2.打八折 3.打七折 4.满300送100):");	
			discount = Integer.parseInt(sc.nextLine());
			System.out.println("请输入商品单价:");	
			price = Double.parseDouble(sc.nextLine());
			System.out.println("请输入商品数量:");	
			num = Integer.parseInt(sc.nextLine());
			System.out.println();	

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

				
				//根据用户输入,将对应的策略对象作为参数传入CashContext对象中
				CashContext cc = new CashContext(discount);
				
				//通过Context的getResult方法的调用,可以得到收取费用的结果
				//让具体算法与客户进行了隔离
				totalPrices = cc.getResult(price,num);
				
				total = total + totalPrices;
				
				System.out.println();	
				System.out.println("单价:"+ price + "元 数量:"+ num +" 合计:"+ totalPrices +"元");	
				System.out.println();
				System.out.println("总计:"+ total+"元");	
				System.out.println();
			}
		}
		while(price>0 && num>0);

		System.out.println();
		System.out.println("**********************************************");

	}
}

简单工厂模式我需要客户端认识两个类,CashSuper和CashFacory,而策略模式与简单工厂结合的用法,客户端就只需要认识一个类CashContext就可以了。耦合更加降低。

说得没错,我们在客户端实例化的是CashContext的对象,调用的是CashContext的方GetResult,这使得具体的收费算法彻底地与客户端分离。连算法的父类CashSuper都不让客户端认识了。

1.7 策略模式解析

策略模式封装了变化。还有什么不足吗?

因为在CashContext里还是用到了switch,也就是说,如果我们需要增加一种算法,比如'满200送50',你就必须要更改CashContext中的switch代码,这总还是让人很不爽呀。那你说怎么办,有需求就得改呀,任何需求的变更都是需要成本的,但是成本的高低还是有差异的。高手和菜鸟的区别就是高手可以花同样的代价获得最大的收益或者说做同样的事花最小的代价。面对同样的需求,然是改动越小越好。""你的意思是说,还有更好的办法?""当然。这个办法就是用到了反射Reflect)技术,不过今天就不讲了,以后会再提它的。""反射真有这么神奇?"小菜疑惑地望向了远方。
注:在抽象工厂模式章节有对反射的讲解。
 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

聊聊测试用例评审流程

测试人员将需求熟悉完成后,开始编写相应的测试用例,待测试用例编写完成后只是测试用例完成前的第一步,后边的流程需要组织线上或线下评审会议等等。 首先要了解测试用例评审的最终目的是什么:提高测试用例的质量和覆盖率&#xff…

利用Node.js实现拉勾网数据爬取

引言 拉勾网作为中国领先的互联网招聘平台,汇集了丰富的职位信息,对于求职者和人力资源专业人士来说是一个宝贵的数据源。通过编写网络爬虫程序,我们可以自动化地收集这些信息,为求职决策和市场研究提供数据支持。Node.js以其非阻…

【Frida】【Android】08_爬虫之网络通信库okhttp3

🛫 系列文章导航 【Frida】【Android】01_手把手教你环境搭建 https://blog.csdn.net/kinghzking/article/details/136986950【Frida】【Android】02_JAVA层HOOK https://blog.csdn.net/kinghzking/article/details/137008446【Frida】【Android】03_RPC https://bl…

【Spring】分别基于XML、注解和配置类实现Spring的IOC(控制反转)

目录 1、理解loC是什么 2、基于XML实现Spring的IOC(这种方式已经不怎么使用了) 3、基于注解实现Spring的IOC 4、基于javaConfig实现Spring的IOC 5、总结 1、理解loC是什么 lOC:lnversion of Control 控制反转,简称就是 IOC 控…

如何使用极狐GitLab Maven 仓库?

本文作者:徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了如何使用极狐GitLa…

Yarn与Zookeeper的介绍

Yarn--三大调度策略 FIFO(先进先出): 目前几乎已经没有人使用了. 类似于: 单行道. 好处: 每个计算任务能独享集群100%的资源. 弊端: 不能并行执行, 如果大任务过多, 会导致小任务执行时间过长. Capacity(容量调度): 我们用…

入门教程:Windows搭建C语言和EasyX开发环境

🌟 前言 欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍 如果对你…

【论文阅读】TimesNet: Temporal 2D-Variation Modeling for General Time Series Analysis

TimesNet: Temporal 2D-Variation Modeling for General Time Series Analysis 引用: Wu H, Hu T, Liu Y, et al. Timesnet: Temporal 2d-variation modeling for general time series analysis[C]//The eleventh international conference on learning representa…

学习 MongoDB:打开强大的数据库技术大门

一、基本概念 MongoDB 是一个基于分布式文件存储的文档数据库,由 C 语言编写。它旨在为 Web 应用提供可扩展的高性能数据存储解决方案。 相信MySQL我们非常的熟悉,那么MySQL的表结构与MongoDB的文档结构进行类比的话可能更好理解MongoDB。 MySQL的数据…

联通iccid 19转20 使用luhn 算法的计算公式

联通iccid 19转20 使用luhn 算法的计算公式 第一次对接iccid 才知道 使用的是luhn 算法 19转20位 文章来源于 文章来源 当时也是一脸懵逼 的状态,然后各种chatgpt 寻找,怎么找都发现不对,最后看到这片java的文章实验是正确的,因…

ubuntu生成core文件的设置方法

core文件可以很方便的帮助我们查找程序挂的问题,因此在程序挂后生成core文件的很有必要的。 1、查看ulimit参数 ulimit -a 如果core file size是0 需要设置其最大容量。按下面步骤操作 2、设置core文件大小,两种方法 临时生效,重启设备失…

WPF学习笔记-FlowDocument流文档基础知识和基本操作

文章目录 概述一、块元素和内联元素1.1 块元素(Block类)1.2 内联元素(Inline类)二、Paragraph元素2.1 基本属性设置2.2 将内联元素Inline添加到Inlines中2.3 设置中西文字体不一样 三、Table元素3.1 添加新的Table3.2 添加列3.3 添…

采用C#.net6.0+Vue,Ant-Design技术开发的一套大型医院手术麻醉信息系统源码,系统成熟,运行稳定

手术麻醉信息系统源码,C#手麻系统源码,自主版权应用案例(适合上项目) 手术麻醉信息系统可以实现手术室监护仪、麻醉机、呼吸机、输液泵等设备输出数据的自动采集,采集的数据能据如实准确地反映患者生命体征参数的变化&…

前端、后端上传文件到OSS,简明记录

前端、后端上传文件到OSS,简明记录 上传文件到oss的方式: **后端上传:**文件先要从页面上传到后端存起来,再通过后端发送到oss,然后后端将存起来的文件删除(当然可以不删)。 **前端上传&…

Unix 网络编程, Socket 以及bind(), listen(), accept(), connect(), read()write()五大函数简介

Unix网络编程是针对类Unix操作系统(包括Linux、BSD以及其他遵循POSIX标准的操作系统)进行网络通信开发的技术领域。网络编程涉及创建和管理网络连接、交换数据以及处理不同层次网络协议栈上的各种网络事件。在Unix环境中,网络编程通常涉及到以…

华为ensp中ospf多区域管理 原理及配置命令(详解)

作者主页:点击! ENSP专栏:点击! ————前言———— OSPF 多区域的主要作用是缩小链路状态数据库和路由表的规模,减少路由更新的频率,提高网络的可扩展性,实现路由过滤和路由汇总&#xff0…

交通标志识别项目 | 基于Tensorflow+SSD实现道路交通标志识别

项目应用场景 面向智能驾驶或自动驾驶场景道路道路交通标志的识别,在交通标志识别的基础上为下一步的智能决策提供前提 项目效果: 项目细节 > 具体参见项目 README.md (1) 安装依赖 Python3.5、TensorFlow v0.12.0、Pickle、OpenCV-Python、Matplotl…

如何利用CSS实现文字滚动效果

1. 使用CSS3的animation属性 CSS3的animation属性可以让元素在一段时间内不停地播放某个动画效果。我们可以利用这个特性来实现文字滚动效果。 我们需要定义一个包含所有需要滚动的文本的容器元素。比如&#xff1a; <div class"scroll-container"><p>…

手机一键换ip地址,解锁网络自由

在数字化时代&#xff0c;手机已经成为我们生活中不可或缺的一部分。随着移动互联网的快速发展&#xff0c;手机用户对于网络安全和隐私保护的需求也日益增强。其中&#xff0c;IP地址作为手机在网络中的标识&#xff0c;扮演着重要的角色。有时&#xff0c;出于隐私保护或网络…

仿真黑科技EasyGo DeskSim 2022

DeskSim2022的FPGA支持多种solver的混合应用&#xff0c;对于每一种solver可以采用不同的仿真步长&#xff0c;以下图模型为例&#xff0c;模型运行在FPGA上&#xff0c;FPGA解算方式采用的是Power Electronic & FPGA Coder解算&#xff0c;其中电力电子电路部分采用了两种…