1、什么是策略模式
在一个成熟的框架中,经常会看到设计模式,比如在springboot的源码里面也是随处可见的。在所有的设计模式中,策略模式是最通用,也是最能体现一个开发思想的设计模式。那么什么是策略模式呢?策略模式就是针对每一种场景有对应的策略,支持横向扩展。也就是说,把选择何种策略的机会交给调用者,将策略构建和选择策略进行一个解耦,提高业务的扩展性和代码的健壮性。
不过也要注意,不能过于设计,也就是说不能因为要使用策略模式而忽略了基础的if else。代码还是越简单越好,越是复杂的功能,越能通过简单的代码实现,那么才是最厉害的技术。
2、为什么要用策略模式
通过第一部分可知,策略模式可以明显的提高业务的扩展性和代码的健壮性。对于我们开发者而言,策略模式最直观的体现就是去掉了一大堆的if else。比如在一些核心的业务步骤里面,如果出现了很多的if else,那么就会导致后面这块代码无人敢动,也没人敢维护,很不利于项目的稳定运行和发展。
还有一个好处就是,基于策略模式,我们可以通过各个实现类进行自己的业务处理,很好的体现了高内聚低耦合的编程思想。
最后就是,如果你在项目中使用了策略模式,也能把它说的明白,那么在以后的面试中,这将会是一个很重要的加分项。
3、如何使用策略模式
策略模式的定义和好处,我们都已经了解了,那么我们应该怎么使用策略模式呢?在企业项目中,当我们接到产品的需求时,我们首先要对自己的业务进行一个功能设计,分清楚哪些是核心业务,哪些是次要业务。然后看核心业务是否需要支持横向扩展,如果需要,那么我们才进行策略模式的设计。
假设存在这样一种业务需求:
随着业务的发展,你们公司需要接入自己的支付系统。虽然前期可能只有一种支付供应商,如支付宝,但是随着用户量的增长,为了提升用户好感,你们的产品经理肯定会提出接入其他支付供应商,如微信支付、银联支付等。那么为了减小核心代码的变动,我们可以在设计之初就使用策略模式进行考虑。所有的策略模式都需要一个容器(上下文)进行存储,也就是context,然后在使用策略的时候可以直接从该context里面拿出来。
各个类的关系如下:
3.1 定义支付基类和核心抽象方法
支付基类里面主要包含context和一些抽象方法,同时对外提供一个统一的支付调用方法
/**
* @author yinfeng
* @description 支付基类
* @since 2022/6/7 22:06
*/
public abstract class BasePay {
public BasePay() {
// 子类实例化的同时将自己注入context中
CONTEXT.put(this.getType(), this);
}
/**
* 策略模式容器
*/
public final static Map<String, BasePay> CONTEXT = new ConcurrentHashMap<>(10);
/**
* 支付方法,子类实现
*/
public abstract void pay();
/**
* 策略标识,子类实现
*
* @return type
*/
public abstract String getType();
public static void toPay(String type) {
final BasePay payService = CONTEXT.get(type);
if (Objects.isNull(payService)) {
throw new IllegalArgumentException("未找到对应的支付实现类");
}
payService.pay();
}
}
3.2 支付宝支付实现类
/**
* @author yinfeng
* @description 支付宝支付
* @since 2022/6/7 22:32
*/
public class AliPay extends BasePay {
@Override
public void pay() {
// TODO 复杂的支付逻辑
System.out.println("支付宝支付成功");
}
@Override
public String getType() {
return "alipay";
}
}
3.3 微信支付实现类
/**
* @author yinfeng
* @description 微信支付
* @since 2022/6/7 22:32
*/
public class WxPay extends BasePay{
@Override
public void pay() {
// TODO 复杂的支付逻辑
System.out.println("微信支付成功");
}
@Override
public String getType() {
return "wx";
}
}
3.4 银联支付实现类
/**
* @author yinfeng
* @description 银联支付
* @since 2022/6/7 22:33
*/
public class BankPay extends BasePay {
@Override
public void pay() {
// TODO 复杂的支付逻辑
System.out.println("银联支付成功");
}
@Override
public String getType() {
return "bank";
}
}
3.4 写个测试类测试一下
/**
* @author yinfeng
* @description 支付测试类
* @since 2022/6/7 22:34
*/
public class PayTest {
public static void main(String[] args) {
// 假如接口来的参数是任意的 wx/alipay/bank
final List<String> payList = Arrays.asList("wx", "alipay", "bank");
final Random random = new Random();
for (int i = 0; i < 200; i++) {
String type = payList.get(random.nextInt(3));
System.out.println("type=" + type);
BasePay.toPay(type);
}
}
/*
初始化所有支付实现类
*/
static {
new WxPay();
new AliPay();
new BankPay();
}
}
测试效果如下:
可以看到我们的测试效果已经能满足咱们的需求,同时支付实现类也支持==横向扩展==,通过策略模式很好地提高我们代码的健壮性。
4、总结
学习很多时候都不一定能马上看到效果,但只要你学了总有一天会用到,希望大家能坚持学习。策略模式是一种很重要的设计思想,在我们的项目中可以经常用到。掌握了这个设计思想,对于我们以后的项目设计和面试都会有很大的帮助,最后祝大家找到自己心怡的工作。