设计模式之策略(加简单工厂模式)

本文介绍策略模式与简单工厂模式结合应用在超市收银结账的案例。通过定义算法并封装,使得算法可以在不修改客户端的情况下进行更换。具体包括正常收费、打折收费及满减等场景。

案例:超市收银结账

咋们由浅到深。

需求一

要求通过商品单价和商品数量计算总价格
这个简单,一两分钟就好

public static void main(String[] args) {
		//模拟一个商品的单价
		double unitPrice = 10.50d;
		//模拟商品的数量
		int num = 6;
		System.out.println(num * unitPrice);
	}

需求二

超市打八折

// 模拟打折
	private static final double discount = 0.8d;
	public static void main(String[] args) {
		//模拟一个商品的单价
		double unitPrice = 10.50d;
		//模拟商品的数量
		int num = 6;
		double money = discount * (num * unitPrice);
		System.out.println(money);
	}

从这里可以看出,超市的活动会很多,打的折扣不同,或者是满多少送多少,又或者是什么活动也没有,它们的相同的也就是初始参数不同

需求三

增加满减
使用简单工厂来进行操作一下
首先我们先定义一个现金收取方法抽象类

//现金收取方法抽象类
public abstract class CashSuper {
	public abstract double acceptCash(double money);
}

定义实体类去继承现金收取方法抽象类

//正常收费
public class CashNormal extends CashSuper {
	@Override
	public double acceptCash(double money) {
		return money;
	}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//打折收费
public class CashRebate extends CashSuper {
	// 打折
	private double moneyRebate = 1d;
	// 初始化定义打折率
	public CashRebate(String moneyRebate) {
		this.moneyRebate = Double.parseDouble(moneyRebate);
	}
	@Override
	public double acceptCash(double money) {
		return moneyRebate * money;
	}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//满减
public class CashRrturn extends CashSuper {
	//初始定义
	// 满
	private double moneyCondition = 0.0d;
	// 返
	private double moneyReturn = 0.0d;

	public CashRrturn(String moneyCondition, String moneyReturn) {
		this.moneyCondition = Double.parseDouble(moneyCondition);
		this.moneyReturn = Double.parseDouble(moneyReturn);
	}
	@Override
	public double acceptCash(double money) {
		if (money >= moneyCondition) {
			money = money - Math.floor(money / moneyCondition) * moneyReturn;
		}
		return money;
	}
}

接下来是工厂的创建和界面代码

//我是工厂
public class CashFactory {
	public CashSuper creatCashAccept(String type) {
		CashSuper cs = null;
		switch (type) {
		case "正常收费":
			cs = new CashNormal();
			break;
		case "满300减100":
			cs = new CashRrturn("300", "100");
			break;
		case "打八折":
			cs = new CashRebate("0.8");
			break;
		default:
			break;
		}
		return cs;
	}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//我是界面
public class XXX {
	public static void main(String[] args) {
		//模拟一个商品的单价
		double unitPrice = 100d;
		//模拟商品的数量
		int num = 7;
		// 购物类型
		String type = "满300减100";
		// 获取相应类型的对象
		CashSuper csSuper = new CashFactory().creatCashAccept(type);
		double money = csSuper.acceptCash(num * unitPrice);
		System.out.println(money);
	}
}

上面使用简单工厂来实现的,接下来我们使用策略模式来

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

之前写的抽象类和子类都不用改变 ,需要写一个CashContext类,并改一下界面就好了

//上下文
public class CashContext {
	private CashSuper cs = null;
	public CashContext(CashSuper cs){
		this.cs = cs;
	}
	public double getResult(double money){
		return cs.acceptCash(money);
	}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//我是界面
public class XXX {
	public static void main(String[] args) {
		//模拟一个商品的单价
		double unitPrice = 100d;
		//模拟商品的数量
		int num = 7;
		// 购物类型
		String type = "满300减100";
		CashContext cc = null;
		switch (type) {
		case "正常收费":
			cc = new CashContext(new CashNormal());
			break;
		case "满300减100":
			cc = new CashContext(new CashRrturn("300", "100"));
			break;
		case "打八折":
			cc = new CashContext(new CashRebate("0.8"));
			break;
		default:
			break;
		}
		double result = cc.getResult(num * unitPrice);
		System.out.println(result);
	}
}

使用了两种模式后发现:工厂模式你需要让界面认识两个类CashSuper和CashFactory,而策略模式只需要让界面知道CashContext就行

不过策略模式又让界面去判断使用那个算法。so

简单工厂模式与策略模式的结合

还是抽象类与其子类不需要改变,只需要改界面代码和上下文(CashContext)

//上下文
public class CashContext {
	private CashSuper cs = null;
	// 使用构造器去初始化CashSuper并判断算法
	public CashContext(String type) {
		switch (type) {
		case "正常收费":
			cs = new CashNormal();
			break;
		case "满300减100":
			cs = new CashRrturn("300", "100");
			break;
		case "打八折":
			cs = new CashRebate("0.8");
			break;
		}
	}
	public double getResult(double money){
		return cs.acceptCash(money);
	}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//我是界面
public class XXX {
	public static void main(String[] args) {
		//模拟一个商品的单价
		double unitPrice = 100d;
		//模拟商品的数量
		int num = 7;
		// 购物类型
		String type = "满300减100";
		// 传一个类型就可以了
		CashContext cc = new CashContext(type);
		double result = cc.getResult(num * unitPrice);
		System.out.println(result);
	}
}

现在要改什么算法,只需要在CashContext里面更改更改就好,不过还是很麻烦,每次都需要去更改swith代码。
这个还有更简单的办法,用到了反射的技术,以后会提到的,嘿嘿
反射反射,程序员的快乐
高手与菜鸟的区别在于做同样的事,花最小的代价。或者花同样的代价获取最大的收益。
就比如一样的需求更改,十分钟后,高手都开始玩第二局王者荣耀了。菜鸟还刚理清代码。
加油一起努力吧。程序员!

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值