聊一下策略模式的一种使用方式

141 阅读3分钟

业务场景

我们部门的业务模块需要对接另一个系统的很多接口,且它这个系统经历过重构升级,导致一些接口在新老版本的请求参数、请求类型、返回值不一样。但是我们依然要去兼容它的多个版本。

我的方案是:

  1. 单独拆出来一个模块去做多版本兼容的工作,后续需要添加版本或者直接更换下游系统接口URL的时候,只需要维护这个模块就好了,不需要再去修改我们的业务产品包。
  2. 在这个模块中同样将核心业务逻辑代码与对接下游接口的代码做了分离,并且采用策略模式去做多版本兼容,这样在后期维护版本的时候只需要去修改指定的策略处理类就好,无需修改核心业务逻辑代码。

优化之前的伪代码

如果不使用策略模式进行优化,那么这部分代码的伪代码基本上如下:

public Result test() {
    switch(版本) {
        case "3.0":
            return handleThreeVersion();
        case "4.0":
            return handleFourVersion();
        default:
            throw new TJCException("版本不存在");       
    }
}

实际上我们有20多个接口需要与这个对接,如果每个业务里有这样写的话,那岂不是要重复写20多份了。这样如果后期再增加一个新的版本,我们后期的维护工作量也是相当的大。

使用策略模式进行优化

一、首先我们定制一个前端页面用来配置外部系统的信息,其中维护外部系统的版本号。

二、我们定义两个枚举类,分别用来维护业务信息和版本信息。

// 接口业务信息枚举类
public enum OutSystemApiTypeEnum {
    // 枚举值作为制定业务策略的前缀
    TEXT_API("TextApi")
}

// 外部系统版本信息枚举类
public enum OutSystemVersionEnum {
    // 第一个值与前端页面维护的版本一致,第二个值作为业务策略的后缀
    Three("3.0", "ThreeHandle"),
    Four("4.0", "FourHandle"),
}

三、创建对应的处理类,将两个枚举类中的前缀和后缀拼接作为对应处理类的类名。

// 先定义一个接口
public interface RequestOutSystemApiHandle {
    // 每个处理类时机的处理方法
    <T> CustemResult<T> execute(....);
}

// 编写处理类,类名为两个枚举类前缀后缀组合
@Component
public class TextApiThreeHandle implements RequestOutSystemApiHandle {
    public CustemResult<T> execute(...) {
        // 业务处理
        // 封装返回
    }
}

四、创建工厂类

@Component
public class RequestOutSystemApiFactory {

    @Autowired
    private ApplicationContext applicationContext;

    public RequestOutSystemApiHandle getHandle(OutSystemApiTypeEnum apiTypeEnum, String version) {
        // 根据两个枚举类前后缀获取对应处理类Bean的名称
        String beanName = apiTypeEnum.getApiType() + OutSystemVersionEnum.getValueByVersion(version);
        // 获取对应的bean
        return applicationContext.getBean(beanName, RequestOutSystemApiHandle.class);
    }
}

五、业务代码

public Result test() {
    // 通过这种方式动态的调用指定Bean的execute方法处理业务逻辑
    requestOutSystemApiFactory.getHandle(OutSystemApiTypeEnum.TEXT_API, "传过来的版本号")
    .execute(...);
}

六、这样我们后续再添加版本的时候,只需要在版本枚举类中添加对应的版本,并且创建对应的处理器类就好了,不需要去修改业务代码。