策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,并将每个算法封装在具有共同接口的独立类中,使得它们可以在运行时互换使用。这种模式提供了对算法家族进行分装,可以按需动态地改变对象的行为。
抽象提取理论:
代码需求:模拟商场收银软件,营业员根据客户购买商品的单价和数量,打折(例如7折,6折)会变化,满减(200-100,300-150)会变化,原价其中之一进行收费。你会如何利用面向对象原则来设计这个demo呢?
策略模式实现:
代码结构图
代码实现:
/**
* 策略抽象类
*/
public abstract class CashSuper {
/**
* 算法方法
* @Param 单价
* @Param 数量
*/
abstract double acceptCash(double price,int number);
}
/**
* 正常算法
*/
public class CashNormal extends CashSuper{
@Override
double acceptCash(double price, int number) {
return price * number;
}
}
/**
* 打折优惠
*/
public class CashRebate extends CashSuper{
/**
* 默认打折折扣率
*/
private double moneyRebate = 1d;
/**
* 设置打折折扣率
*/
public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}
/**
* 实现打折方法
* @param price 单价
* @param number 数量
*/
@Override
double acceptCash(double price, int number) {
return price * number * moneyRebate;
}
}
/**
* 满减算法
*/
public class CashReturn extends CashSuper{
/**
* 返利条件
*/
private double nmoneyConditionn = 0d;
/**
* 返利值
*/
private double nmoneyReturn = 0d;
/**
* 指定返利条件和返利值
* @param nmoneyConditionn 返利条件
* @param nmoneyReturn 返利值
*/
public CashReturn(double nmoneyConditionn, double nmoneyReturn) {
this.nmoneyConditionn = nmoneyConditionn;
this.nmoneyReturn = nmoneyReturn;
}
/**
* 实现打折方法
* @param price 单价
* @param number 数量
*/
@Override
double acceptCash(double price, int number) {
double sum = price * number;
if (nmoneyConditionn> 0 && sum>= nmoneyConditionn){
// Math.floor:向下取整。计算满足多次返利条件情况(根据实际业务)
sum = sum - Math.floor(sum / nmoneyConditionn) * nmoneyReturn;
}
return sum;
}
}
/**
* 获取上下文类
*/
public class CashContext {
private CashSuper cashSuper;
/**
* 初始化时,定义策略
*/
public CashContext(CashSuper cashSuper){
this.cashSuper = cashSuper;
}
/**
* 上下文接口
*/
public double getResult(double num1,int num2){
// 根据策略,调用策略接口
return cashSuper.acceptCash(num1, num2);
}
}
/**
* 客户端
*/
public class StrategyDemo {
public static void main(String[] args) {
// 没有打折优惠
CashContext cashContext = new CashContext(new CashNormal());
System.out.println("无打折优惠:" + cashContext.getResult(200, 1));
// 打7折
CashContext cashContext2 = new CashContext(new CashRebate(0.7d));
System.out.println("打7折优惠:" + cashContext2.getResult(200, 1));
// 满减优惠 满200 优惠100
CashContext cashContext3 = new CashContext(new CashReturn(200,100));
System.out.println("打7折优惠:" + cashContext3.getResult(200, 1));
}
}
输出结果:
无打折优惠:200.0
打7折优惠:140.0
打7折优惠:100.0
在此我们实现了两种优惠方法,通过构造函数的方式可以动态指定打折力度或满减条件。
优化
但是……会出现以下问题
利用简单工厂模式进行优化:
/**
* 获取上下文类
*/
public class CashContext {
private CashSuper cashSuper;
/**
* 初始化时,定义策略
*/
public CashContext(CashSuper cashSuper){
this.cashSuper = cashSuper;
}
/**
* 上下文接口
*/
public double getResult(double num1,int num2){
// 根据策略,调用策略接口
return cashSuper.acceptCash(num1, num2);
}
/**
* 利用简单工厂模式进行优化
* 缺点,这样修改规则或新增规则时 需要给更改switch里面的内容,违背了开闭原则.貌似可以利用反射来再进行一步优化
*/
public CashContext (String way){
switch (way){
case "normal":
cashSuper = new CashNormal();
break;
case "rebate":
cashSuper = new CashRebate(0.7);
break;
case "return":
cashSuper = new CashReturn(200, 100);
break;
default:
cashSuper = new CashNormal();
break;
}
}
}
/**
* 客户端
*/
public class StrategyDemo {
public static void main(String[] args) {
// 没有打折优惠
CashContext cashContext = new CashContext(new CashNormal());
System.out.println("无打折优惠:" + cashContext.getResult(200, 1));
// 打7折
CashContext cashContext2 = new CashContext(new CashRebate(0.7d));
System.out.println("打7折优惠:" + cashContext2.getResult(200, 1));
// 满减优惠 满200 优惠100
CashContext cashContext3 = new CashContext(new CashReturn(200,100));
System.out.println("打7折优惠:" + cashContext3.getResult(200, 1));
// 优化使用 ->> 打7折
CashContext cashContext4 = new CashContext("rebate");
System.out.println("打7折优惠:" + cashContext4.getResult(200, 1));
}
}
100));
System.out.println(“打7折优惠:” + cashContext3.getResult(200, 1));
// 优化使用 ->> 打7折
CashContext cashContext4 = new CashContext("rebate");
System.out.println("打7折优惠:" + cashContext4.getResult(200, 1));
}
}