设计模式之策略模式
程序员文章站
2022-06-13 12:51:57
...
读书笔记:参考 Head First 设计模式,大话设计模式
设计模式要点
- 知道OO基础,并不足以设计出良好的OO系统
- 良好的OO设计必须具备可以复用,可扩充,可维护三个特征
- 模式可以让我们建造出具有良好OO设计质量的系统
- 设计模式被认为是经验验证的OO设计经验
- 模式不是代码,而是真实设计问题的通用解决方案
- 模式不是被发明而是被发现
- 大多数的模式和原则,都着眼于软件变化的主题
- 大多数模式都允许系统局部改变独立于其他部分
- 我们常把系统中会变化的部分抽出来封装
- 模式让开发人员之间有共享的语言,最大化沟通的价值
设计原则
- 封装变化
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
- 针对接口编程,而不是针对实现编程
针对接口编程关键就在于多态,变量的声明类型应该是抽象类或一个接口,具体实现此超类型所产生的对象指定给这个变量,意味着声明类时不用理会以后执行时真正的对象类型
- 多用组合,少用继承
策略模式定义
定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
策略模式结构图
代码样例
需求:一个计算商品数量和单价的小程序,后续逐渐增加需求,8折,满300返100等活动
- 普通实现
public class SimpleCashClient {
public static void main(String[] args) {
System.out.println(cash(300, CashType.NORMAL, 1));
System.out.println(cash(300, CashType.REBATE, 1));
System.out.println(cash(300, CashType.RETURN, 1));
}
public static String cash(int money, CashType type, int num) {
String result = "单价:" + money + " 数量:" + num + " 优惠:" + type.typeName();
int total = money * num;
switch (type) {
case REBATE:
BigDecimal bMoney = new BigDecimal(money);
BigDecimal bRebate = new BigDecimal(0.8);
total = bMoney.multiply(bRebate).intValue() * num;
break;
case RETURN:
if (money >= 300) {
total = money - ((money / 300) * 100);
}
break;
default:
break;
}
return result + "\n 合计:" + total;
}
}
执行结果:
单价:300 数量:1 优惠:无
合计:300
单价:300 数量:1 优惠:8折
合计:240
单价:300 数量:1 优惠:满300减100
合计:200
- 使用策略模式实现
public class CashClient {
public static void main(String[] args) {
System.out.println(cash(300, CashType.NORMAL, 1));
System.out.println(cash(300, CashType.REBATE, 1));
System.out.println(cash(300, CashType.RETURN, 1));
}
public static String cash(int money, CashType type, int num) {
String result = "单价:" + money + " 数量:" + num + " 优惠:" + type.typeName();
int total = new CashContext(type).getResult(money) * num;
return result + "\n 合计:" + total;
}
}
执行结果同上
UML图
context
public class CashContext {
public static enum CashType {
REBATE, RETURN, NORMAL;
public String typeName() {
if (this.name().equals(REBATE.name())) {
return "8折";
} else if (this.name().equals(RETURN.name())) {
return "满300减100";
} else {
return "无";
}
}
}
// 针对接口
private ICash cash = new CashNormal();;
CashContext(CashType type) {
switch (type) {
case REBATE:
cash = new CashRebate(0.8);
break;
case RETURN:
cash = new CashReturn(300, 100);
break;
default:
cash = new CashNormal();
break;
}
}
public int getResult(int money) {
// 多态
return cash.acceptCash(money);
}
}
strategy
public interface ICash {
int acceptCash(int money);
}
public class CashNormal implements ICash {
@Override
public int acceptCash(int money) {
return money;
}
}
public class CashRebate implements ICash {
// 默认不打折
private double rebate = 1;
public CashRebate(double rebate) {
this.rebate = rebate;
}
@Override
public int acceptCash(int money) {
BigDecimal bMoney = new BigDecimal(money);
BigDecimal bRebate = new BigDecimal(rebate);
return bMoney.multiply(bRebate).intValue();
}
}
public class CashReturn implements ICash {
// 返利条件
private int returnCondition = 0;
// 返利金额
private int returnMoney = 0;
public CashReturn(int returnCondition, int returnMoney) {
this.returnCondition = returnCondition;
this.returnMoney = returnMoney;
}
@Override
public int acceptCash(int money) {
if (money >= returnCondition) {
return money - ((money / returnCondition) * returnMoney);
}
return money;
}
}
策略模式解析
策略模式是一种定义一系列算法的方法,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合
策略模式的Strategy类层次,为Context定义了一系列的可供重用的算法或行为,继承有助于析取这些算法中的公共功能
策略模式封装了变化
当不同行为堆砌在一个类中时,难免使用条件语句来选择合适的行为,将这些行为封装在独立的Strategy类中,可以在使用这些行为的类中消除条件语句.
策略模式不光可以封装算法可以封装几乎任何类型的规则,只要需要不同的时间应用不同的业务规则,就可以考虑策略模式
可以用反射进一步代替选择具体实现的逻辑
上一篇: 设计模式之策略模式