1 策略模式概述
策略模式(strategy pattern)的原始定义是:定义一系列算法,将每一个算法封装起来,并使它们可以相互替换。策略模式让算法可以独立于使用它的客户端而变化。
2 策略模式原理
3 策略模式实现
策略模式的本质是通过Context类来作为中心控制单元,对不同的策略进行调度分配。
java
//抽象策略类
public interface Strategy {
void algorithm();
}
java
/**
* 具体策略类
**/
public class ConcreteStrategyA implements Strategy {
@Override
public void algorithm() {
System.out.println("执行策略A");
}
}
java
public class ConcreteStrategyB implements Strategy {
@Override
public void algorithm() {
System.out.println("执行策略B");
}
}
java
/**
* 上下文类: 策略模式的本质就是通过Context类作为控制单元,
* 对不同的策略进行调度分配
**/
public class Context {
//维持一个抽象策略的引用
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
//调用策略类中的算法
public void algorithm(){
strategy.algorithm();
}
}
java
public class Client {
public static void main(String[] args) {
Strategy strategyB= new ConcreteStrategyB();
Context context = new Context(strategyB);
context.algorithm();
}
}
1 ) 不使用设计模式
java
/**
* 回执信息
**/
public class Receipt {
private String message; //回执内容
private String type; //回执类型: MT1101、MT2101、MT4101、MT8104
public Receipt() {
}
public Receipt(String message, String type) {
this.message = message;
this.type = type;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
java
/**
* 回执信息
**/
public class Receipt {
private String message; //回执内容
private String type; //回执类型: MT1101、MT2101、MT4101、MT8104
public Receipt() {
}
public Receipt(String message, String type) {
this.message = message;
this.type = type;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
java
public class Client {
public static void main(String[] args) {
List<Receipt> receiptList = ReceiptBuilder.getReceiptList();
//回执类型: MT1101、MT2101、MT4101、MT8104
for (Receipt receipt : receiptList) {
if("MT1011".equals(receipt.getType())){
System.out.println("接收到MT1011的回执信息");
System.out.println("解析回执内容");
System.out.println("执行业务逻辑A......");
}else if("MT2101".equals(receipt.getType())){
System.out.println("接收到MT2101的回执信息");
System.out.println("解析回执内容");
System.out.println("执行业务逻辑B......");
}else if("MT4101".equals(receipt.getType())){
System.out.println("接收到MT4101的回执信息");
System.out.println("解析回执内容");
System.out.println("执行业务逻辑C......");
}else if("MT8104".equals(receipt.getType())){
System.out.println("接收到MT8104的回执信息");
System.out.println("解析回执内容");
System.out.println("执行业务逻辑D......");
}
//.........
}
}
}
2 ) 使用策略模式进行优化
通过策略模式, 将所有的if-else分支的业务逻辑抽取为各种策略类,让客户端去依
赖策略接口,保证具体策略类的改变不影响客户端.
java
/**
* 回执处理策略接口
**/
public interface ReceiptHandleStrategy {
void handleReceipt(Receipt receipt);
}
具体策略类
java
/**
* 具体策略类
**/
public class MT1101ReceiptHandleStrategy implements ReceiptHandleStrategy {
@Override
public void handleReceipt(Receipt receipt) {
System.out.println("解析报文MT1101: " + receipt.getMessage());
}
}
java
public class MT2101ReceiptHandleStrategy implements ReceiptHandleStrategy {
@Override
public void handleReceipt(Receipt receipt) {
System.out.println("解析报文 MT2101: " + receipt.getMessage());
}
}
策略上下文类(策略接口的持有者)
java
/**
* 上下文类, 持有策略接口,决定执行哪一个具体的策略类
**/
public class ReceiptStrategyContext {
private ReceiptHandleStrategy receiptHandleStrategy;
public void setReceiptHandleStrategy(ReceiptHandleStrategy receiptHandleStrategy) {
this.receiptHandleStrategy = receiptHandleStrategy;
}
//调用策略类中方法
public void handleReceipt(Receipt receipt){
if(receipt != null){
receiptHandleStrategy.handleReceipt(receipt);
}
}
}
策略工厂
java
/**
* 策略工厂类
**/
public class ReceiptHandleStrategyFactory {
public ReceiptHandleStrategyFactory() {
}
//使用Map集合存储策略信息,彻底的消除if...else
private static Map<String,ReceiptHandleStrategy> strategyMap;
//初始化具体策略,保存到map集合
public static void init(){
strategyMap = new HashMap<>();
// strategyMap.put("MT1101",new MT1101ReceiptHandleStrategy());
// strategyMap.put("MT2101",new MT2101ReceiptHandleStrategy());
try {
SAXReader reader = new SAXReader();
String file = "I:\\MSB\\msb_work\\designpattern\\msb-strategy-pattern-14\\src\\main\\resources\\config.xml";
Document document = reader.read(file);
Node node = document.selectSingleNode("/confing/className");
String className = node.getText();
Class clazz = Class.forName(className);
ReceiptHandleStrategy strategy = (ReceiptHandleStrategy) clazz.newInstance();
strategyMap.put("MT1101",strategy);
} catch (Exception e) {
e.printStackTrace();
}
}
//根据回执类型,获取对应的策略对象
public static ReceiptHandleStrategy getStrategy(String receiptType){
return strategyMap.get(receiptType);
}
}
java
public class Client {
public static void main(String[] args) {
//模拟回执
List<Receipt> receiptList = ReceiptBuilder.getReceiptList();
//策略上下文
ReceiptStrategyContext context = new ReceiptStrategyContext();
//策略模式最主要的工作: 将策略的 定义, 创建, 使用这三部分进行了解耦.
for (Receipt receipt : receiptList) {
//获取策略
ReceiptHandleStrategyFactory.init();
ReceiptHandleStrategy strategy = ReceiptHandleStrategyFactory.getStrategy(receipt.getType());
//设置策略
context.setReceiptHandleStrategy(strategy);
//执行策略
context.handleReceipt(receipt);
}
}
}
经过上面的改造,我们已经消除了if-else的结构,每当新来了一种回执,只需
要添加新的回执处理策略,并修改ReceiptHandleStrategyFactory中的Map
集合。如果要使得程序符合开闭原则,则需要调整ReceiptHandleStrategyFactory中处理策略的获取方式,通过反射的方式,获取指定包下的所IReceiptHandleStrategy实现类,然后放到字典Map中去.
5 策略模式总结