1.策略模式基本介绍
1)策略模式(Strategy Pattern)中,定义算法族(策略组),分别封装起来,让他们之间可以相互替换,从模式
让算法的变化独立于使用算法的客户
2)这算法体现了几个设计原则:第一、把变化的代码从不变的代码中分离出来;第二、针对接口编程而不是具体类(
定义了策略接口);第三、多用组合/聚合,少用继承
2.策略模式类图
3.策略模式应用(策略模式+Map字典)
应用场景:
物流行业中,通常会涉及到EDI报文(XML格式文件)传输和回执接收,每发送一份EDI报文,后续都会收到与之关联的回执(标识该数据在第三方系统中的流转状态)。
这里枚举几种回执类型:MT1101、MT2101、MT4101、MT8104、MT8105、MT9999,系统在收到不同的回执报文后,会执行对应的业务逻辑处理。当然,实际业务场景并没有那么笼统,这里以回执处理为演示案例
代码示例:
public class Receipt {
/**
* 回执信息
*/
String message;
/**
* 回执类型(`MT1101、MT2101、MT4101、MT8104、MT8105、MT9999`)
*/
String type;
}
public class ReceiptBuilder {
public static List<Receipt> generateReceiptList(){
//直接模拟一堆回执对象
List<Receipt> receiptList = new ArrayList<>();
receiptList.add(new Receipt("我是MT2101回执喔","MT2101"));
receiptList.add(new Receipt("我是MT1101回执喔","MT1101"));
receiptList.add(new Receipt("我是MT8104回执喔","MT8104"));
receiptList.add(new Receipt("我是MT9999回执喔","MT9999"));
//......
return receiptList;
}
}
传统做法-if-else分支
List<Receipt> receiptList = ReceiptBuilder.generateReceiptList();
//循环处理
for (Receipt receipt : receiptList) {
if (StringUtils.equals("MT2101",receipt.getType())) {
System.out.println("接收到MT2101回执");
System.out.println("解析回执内容");
System.out.println("执行业务逻辑");
} else if (StringUtils.equals("MT1101",receipt.getType())) {
System.out.println("接收到MT1101回执");
System.out.println("解析回执内容");
System.out.println("执行业务逻辑");
} else if (StringUtils.equals("MT8104",receipt.getType())) {
System.out.println("接收到MT8104回执");
System.out.println("解析回执内容");
System.out.println("执行业务逻辑");
} else if (StringUtils.equals("MT9999",receipt.getType())) {
System.out.println("接收到MT9999回执");
System.out.println("解析回执内容");
System.out.println("执行业务逻辑");
System.out.println("推送邮件");
}
// ......未来可能还有好多个else if
}
策略模式+简单工厂,代码如下
@Data
public class Receipt {
/**
* 回执信息
*/
String message;
/**
* 回执类型(`MT1101、MT2101、MT4101、MT8104、MT8105、MT9999`)
*/
String type;
}
/**
* @Description: 回执处理策略接口
* @Auther: wuzhazha
* 策略接口
*/
public interface IReceiptHandleStrategy {
void handleReceipt(Receipt receipt);
}
//策略接口实现类,也就是具体的处理者
public class Mt2101ReceiptHandleStrategy implements IReceiptHandleStrategy {
@Override
public void handleReceipt(Receipt receipt) {
System.out.println("解析报文MT2101:" + receipt.getMessage());
}
}
public class Mt1101ReceiptHandleStrategy implements IReceiptHandleStrategy {
@Override
public void handleReceipt(Receipt receipt) {
System.out.println("解析报文MT1101:" + receipt.getMessage());
}
}
public class Mt8104ReceiptHandleStrategy implements IReceiptHandleStrategy {
@Override
public void handleReceipt(Receipt receipt) {
System.out.println("解析报文MT8104:" + receipt.getMessage());
}
}
public class Mt9999ReceiptHandleStrategy implements IReceiptHandleStrategy {
@Override
public void handleReceipt(Receipt receipt) {
System.out.println("解析报文MT9999:" + receipt.getMessage());
}
}
策略上下文类(策略接口的持有者)
/**
* @Description: 上下文类,持有策略接口
* @Auther: wuzhazha
*/
public class ReceiptStrategyContext {
private IReceiptHandleStrategy receiptHandleStrategy;
/**
* 设置策略接口
* @param receiptHandleStrategy
*/
public void setReceiptHandleStrategy(IReceiptHandleStrategy receiptHandleStrategy) {
this.receiptHandleStrategy = receiptHandleStrategy;
}
public void handleReceipt(Receipt receipt){
if (receiptHandleStrategy != null) {
receiptHandleStrategy.handleReceipt(receipt);
}
}
}
/**
* @Description: 策略工厂
* @Auther: wuzhazha
*/
public class ReceiptHandleStrategyFactory {
private static Map<String,IReceiptHandleStrategy> receiptHandleStrategyMap;
private ReceiptHandleStrategyFactory(){
this.receiptHandleStrategyMap = new HashMap<>();
this.receiptHandleStrategyMap.put("MT2101",new Mt2101ReceiptHandleStrategy());
this.receiptHandleStrategyMap.put("MT8104",new Mt8104ReceiptHandleStrategy());
}
public static IReceiptHandleStrategy getReceiptHandleStrategy(String receiptType){
return receiptHandleStrategyMap.get(receiptType);
}
}
客户端
public class Client {
public static void main(String[] args) {
//模拟回执
List<Receipt> receiptList = ReceiptBuilder.generateReceiptList();
//策略上下文
ReceiptStrategyContext receiptStrategyContext = new ReceiptStrategyContext();
for (Receipt receipt : receiptList) {
//获取并设置策略
IReceiptHandleStrategy receiptHandleStrategy = ReceiptHandleStrategyFactory.getReceiptHandleStrategy(receipt.getType());
receiptStrategyContext.setReceiptHandleStrategy(receiptHandleStrategy);
//执行策略
receiptStrategyContext.handleReceipt(receipt);
}
}
}
如果要使得程序符合开闭原则,则需要调整ReceiptHandleStrategyFactory中处理策略的获取方式,
通过反射的方式,获取指定包下的所有IReceiptHandleStrategy实现类,然后放到字典Map中去。
系统学习设计模式:设计模式内容聚合