前言
先来思考几个问题:策略模式用在哪里,怎么使用,思想是什么
本次来一点实际开发中会用到的小技巧。
比如平时大家是否都会写类似这样的代码
if (a) {
// 微信支付
} else if(b) {
// 阿里支付
} else if(c) {
// 银联支付
}
试想而知,条件少还好,一旦 elseif 过多这里的逻辑将会比较混乱,并很容易出错。所以就有了我们今天要讲的设计模式--策略模式
刚开始条件较少,也就没管那么多直接写的,这次终于忍无可忍就把他重构了,重构之后这里的结构如下:
String className = PayEnumStrategy.valueOf(strategyType).getClassName();
return (PayStrategy) Class.forName(className).newInstance();
实现思路草图
** 整体思路如下:**
1、定义一个 InnerCommand 接口,其中有一个 process 函数交给具体的业务实现。
2、根据自己的业务,会有多个类实现 InnerCommand 接口;这些实现类都会注册到 SpringBean 容器中供之后使用。
3、通过客户端输入命令,从 SpringBean 容器中获取一个 InnerCommand 实例。
4、执行最终的 process 函数。
话不多说,那我们就干起来,我现在使用枚举Enum来实现的,也可以用mysql实现。
代码撸起来
一、准备工作--引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
二、准备工作--枚举
public enum PayEnumStrategy {
ALI_PAY("com.qw.boot.strategy.service.impl.AliPayStrategy"),
WECHAT_PAY("com.qw.boot.strategy.service.impl.WeChatPayStrategy");
private String className;
PayEnumStrategy(String className) {
this.setClassName(className);
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}
三、逻辑接口 PayStrategy.java
public interface PayStrategy {
String toPayHtml();
}
四、每段逻辑的实现 WeChatPayStrategy.java 和 AliPayStrategy.java
@Service
public class WeChatPayStrategy implements PayStrategy {
@Override
public String toPayHtml() {
return "调微信接口!!!WxPayStrategy";
}
}
@Service
public class AliPayStrategy implements PayStrategy {
@Override
public String toPayHtml() {
return "调用阿里支付宝接口!!!AliPayStrategy";
}
}
五、核心获取上下文。StrategyFactory.java
public class StrategyFactory {
public static PayStrategy getPayEnumStrategy(String strategyType) {
try{
String className = PayEnumStrategy.valueOf(strategyType).getClassName();
return (PayStrategy) Class.forName(className).newInstance();
} catch (Exception e){
e.printStackTrace();
return null;
}
}
}
六、接口测试 TestController.java
@Controller
@RequestMapping("test")
public class TestController {
@Autowired
private PayContextStrategy payContextStrategy;
@RequestMapping("toPayHtml")
public String toPayHtml(String payCode){
String ret = payContextStrategy.toPayHtml(payCode);
return ret;
}
}
七、最后我们来一个根据code获取哪一个策略的判断
@Component
public class PayContextStrategy {
public String toPayHtml(String payCode) {
if (StringUtils.isEmpty(payCode)) {
return "payCode不可为空";
}
PayStrategy payStrategy = StrategyFactory.getPayEnumStrategy(payCode);
if (payStrategy == null){
return "没有找到具体的实现";
}
return payStrategy.toPayHtml();
}
}
这样就大功告成了!!!
尾声:我们来回顾前面几个问题?
1、策略模式用在哪里,怎么使用,思想是什么
1、策略模式一般用在有很多种方式处理,但前面是一样的行为,比如if很多来判断实行每一个策略
2、怎么使用:定义多个实现方法,来实现同一个接口,这也就是不同的策略,再来根据枚举来对应实现每一个策略
3、思想就是:根据class类型获取注册到spring中的处理器上下文
总结:
利用策略模式可以简化繁杂的if else代码,方便维护,而利用自定义注解和自注册的方式,可以方便应对需求的变更。本文只是提供一个大致的思路,还有很多细节可以灵活变化,例如使用枚举类型、或者静态常量,作为支付的类型,相信你能想到更多更好的方法。