什么是策略模式
一个行为多种实现。基于一种行为,委派给不同的对象去管理。可以解决多重if判断和switch。
比如第三方支付 支付宝支付,微信支付,苹果支付;如下图所示
不使用策略模式的代码如下
如果现在再来一个小米钱包支付,就需要再原基础代码上进行改动。改动如下
这样就会有个缺点,每次新增一个支付功能,就需要在基础代码上做改动,很显然的违背的开闭原则
使用策略模式对以上代码进行改进
声明一个支付的抽象类,定义一个支付唯一标识,一个支付方法(由字类实现),和一个构造函数。
package com.strategy;
/**
* <br>
* create by liuqi 2020/10/11
**/
public abstract class AbstractPayStrategy {
/**
* 支付唯一标识
*/
private String payCode;
public AbstractPayStrategy(String payCode) {
this.payCode = payCode;
}
/**
* 声明抽象的支付方法, 由字类实现
*/
public abstract String pay();
public String getPayCode() {
return this.payCode;
}
}
支付宝支付的实现类
package com.strategy.impl;
import com.strategy.AbstractPayStrategy;
/**
* <br>
* create by liuqi 2020/10/11
**/
public class AliPayStrategyImpl extends AbstractPayStrategy {
public AliPayStrategyImpl() {
super("ali_pay");
}
@Override
public String pay() {
return "支付宝支付 AliPayStrategyImpl";
}
}
微信支付的实现类
package com.strategy.impl;
import com.strategy.AbstractPayStrategy;
/**
* <br>
* create by liuqi 2020/10/11
**/
public class WeChatPayStrategyImpl extends AbstractPayStrategy {
public WeChatPayStrategyImpl() {
super("weChat_pay");
}
@Override
public String pay() {
return "微信支付 WeChatPayStrategyImpl";
}
}
苹果支付的实现类
package com.strategy.impl;
import com.strategy.AbstractPayStrategy;
/**
* <br>
* create by liuqi 2020/10/11
**/
public class ApplePayStrategyImpl extends AbstractPayStrategy {
public ApplePayStrategyImpl() {
super("apple_pay");
}
@Override
public String pay() {
return "苹果支付 ApplePayStrategyImpl";
}
}
PayStrategyContext 上下文代码
package com.context;
import com.strategy.AbstractPayStrategy;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.reflections.Reflections;
/**
* 支付策略模式 的上下文环境
*
* <br>
* create by liuqi 2020/10/11
**/
public class PayStrategyContext {
/**
* 存放 {@link AbstractPayStrategy 支付策略模式的实现类}
*/
static final Map<String, AbstractPayStrategy> strategyMap = new HashMap<String, AbstractPayStrategy>();
/**
* 这是将 {@link AbstractPayStrategy 支付策略模式} 所有实现类通过反射加载到 {@link #strategyMap} 集合中
* 实际项目开发 用SpringBean实现
*/
static {
/* 扫码 com.strategy.impl 这个包 */
Reflections reflections = new Reflections("com.strategy.impl");
/* 获取 com.strategy.impl 此包下 所有的 AbstractPayStrategy 实现类*/
Set<Class<? extends AbstractPayStrategy>> subTypesOf = reflections.getSubTypesOf(AbstractPayStrategy.class);
subTypesOf.forEach(aClass -> {
try {
AbstractPayStrategy payStrategy = aClass.newInstance();
strategyMap.put(payStrategy.getPayCode(), payStrategy);
} catch (Exception e) {
}
});
}
/**
* 获取一个支付实现类
* @param payCode 支付标识
* @return
*/
public static AbstractPayStrategy getAbstractPayStrategy(String payCode) {
AbstractPayStrategy payStrategy = strategyMap.get(payCode);
if (payStrategy == null) {
throw new NullPointerException("找不到支付实现类; payCode = " + payCode);
}
return payStrategy;
}
/**
* 执行 pay()
* @param payCode 支付标识
* @return
*/
public static String pay(String payCode) {
return getAbstractPayStrategy(payCode).pay();
}
}
Reflections 依赖
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
</dependency>
进行测试结果,。没有了多重的if判断,只需要一行代码 PayStrategyContext.pay(payCode),业务代码就简洁了很多。
现在再添加一个小米钱包支付就很简单了,因为前面指定了扫码路径是 com.strategy.impl,所以再com.strategy.impl包下再新增一个小米钱包支付类 代码如下
package com.strategy.impl;
import com.strategy.AbstractPayStrategy;
/**
* <br>
* create by liuqi 2020/10/11
**/
public class XiaoMiPayStrategyImpl extends AbstractPayStrategy {
public XiaoMiPayStrategyImpl() {
super("xiaomi_pay");
}
@Override
public String pay() {
return "小米钱包支付 XiaoMiPayStrategyImpl";
}
}
再看下测试效果,就有 小米钱包支付了。
总结
策略模式代码量是很多,但是每次新增一个功能实现,不需要再原基础上修改代码,而是继承或实现指定接口即可。
非常的便于拓展业务与封装。