策略模式+简单工厂

以实际案例为主,第三方服务(例如微信、支付宝、支付核心等)回调我们服务的时候,它会带上一个字段代表本次回调的事件类型(假设字段名为:event)。

事件event的类型有很多种,每一种事件所对应处理的逻辑也不一样,如果不用设计模式的话,就如同以下代码写if-else

@RestController
@RequestMapping(value = "/**/server/paycore")
@Api(tags = "G04-PayCoreController",  value= "支付核心回调控制层")
@Slf4j
public class PayCoreController {

    @ApiOperation (value = "G0401-支付核心通知回调", notes = "支付核心通知回调")
    @PostMapping ("/callback")
    public void payCorePayResult(@RequestBody JSONObject eventJson, HttpServletRequest request, HttpServletResponse response) throws Exception{
·     //获取事件类型   String event
= eventJson.getString("event").toUpperCase(); if (StringUtils.equals("event1",event)){ System.out.println("接收event1回调"); System.out.println("执行event1相关业务逻辑"); } else if (StringUtils.equals("event2",event)){ System.out.println("接收event2回调"); System.out.println("执行event2相关业务逻辑"); } else if (StringUtils.equals("event3",event)){ System.out.println("接收event3回调"); System.out.println("执行event3相关业务逻辑"); } // ......未来可能还有好多个else if } }

在遇到if-else的分支业务逻辑比较复杂时,我们都习惯于将其抽出一个方法或者封装成一个对象去调用,这样整个if-else结构就不会显得太臃肿。就上面例子,当回执的类型越来越多时,分支else if 就会越来越多,每增加一个回执类型,就需要修改或添加if-else分支,违反了开闭原则(对扩展开放,对修改关闭)

因此引入“策略模式+简单工厂”相结合。

我们知道, 策略模式的目的是封装一系列的算法,它们具有共性,可以相互替换,也就是说让算法独立于使用它的客户端而独立变化,客户端仅仅依赖于策略接口 。在上述场景中,我们可以把if-else分支的业务逻辑抽取为各种策略,我们可以将这段逻辑抽取到工厂类中去,这就是策略模式+简单工厂,代码如下:

@RestController
@RequestMapping(value = "/**/server/paycore")
@Api(tags = "G04-PayCoreController",  value= "支付核心回调控制层")
@Slf4j
public class PayCoreController {

    @ApiOperation (value = "G0401-支付核心通知回调", notes = "支付核心通知回调")
    @PostMapping ("/callback")
    public R payCorePayResult(@RequestBody JSONObject eventJson, HttpServletRequest request, HttpServletResponse response) throws Exception{
        // TODO: 2021/9/8 待优化
        String event = eventJson.getString("event").toUpperCase();
        PayCoreCallbackStrategyService payCoreCallbackStrategy = EventFactory.getPayCoreCallbackStrategy(event);
        if (payCoreCallbackStrategy != null){
            payCoreCallbackStrategy.event(eventJson,request,response);
        }else {
            return R.failed("不存在该event事件");
        }
        return R.success();
    }
}
controller层
/**
 * @Description:事件工厂
 * @author: wph
 * @date: 2021/9/8
 */
@Component
@Slf4j
public class EventFactory {

    private static Map<String, PayCoreCallbackStrategyService> callbackStrategyServiceMap;

    private EventFactory() throws Exception{
        callbackStrategyServiceMap = new HashMap<>();;
        //通过反射的方式,获取指定包下的所有PayCoreCallbackStrategyService实现类,然后防到callbackStrategyServiceMap里
        String path = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                .concat(ClassUtils.convertClassNameToResourcePath("com.caih.linkfin.gjfs.api.modules.callback.service.impl"))
                .concat("/*.class");// /*.class表示当前包名下所有类,/**/*.class表示impl包名下的所有子包的类
        ResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = pathMatchingResourcePatternResolver.getResources(path);
        MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(pathMatchingResourcePatternResolver);
        for (Resource resource : resources){
            MetadataReader metadataReader = readerFactory.getMetadataReader(resource);
            //扫描到的类名
            String className = metadataReader.getClassMetadata().getClassName();
            Class<?> clazz = Class.forName(className);
            //获取@service注解
            Service serviceAnnotation = clazz.getAnnotation(Service.class);
            if (serviceAnnotation != null){
                PayCoreCallbackStrategyService serviceImplBean = (PayCoreCallbackStrategyService)clazz.newInstance();
                //如果该service没有设置value,则用类名当作key
                if (StringUtils.isEmpty(serviceAnnotation.value())){
                    callbackStrategyServiceMap.put(clazz.getSimpleName(),serviceImplBean);
                }else{
                    callbackStrategyServiceMap.put(serviceAnnotation.value(),serviceImplBean);
                }
            }
        }
    }

    /**
     * @Description: 根据event事件名称获取对应的bean
     * @author: wph
     * @date: 2021/9/8
     * @param event
     */
    public static PayCoreCallbackStrategyService getPayCoreCallbackStrategy(String event){
        return callbackStrategyServiceMap.get(event);
    }
EventFactory 策略工厂
/**
 * @Description: 支付核心回调策略服务
 * @author: wph
 * @date: 2021/9/5
 */
public interface PayCoreCallbackStrategyService {
    /**
     * @Description: 响应事件
     * @author: wph
     * @date: 2021/9/5
     * @param eventJson 响应体
     */
    void event(JSONObject eventJson, HttpServletRequest request, HttpServletResponse response) throws Exception;
}
StrategyService工厂服务
/**
 * @Description:工资单结果事件处理
 * @author: wph
 * @date: 2021/9/5
 */
@Service("PAYRESULT")
@Slf4j
public class PayResult implements PayCoreCallbackStrategyService {

    /**
     * @Description: 响应事件
     * @author: wph
     * @date: 2021/9/5
     * @param eventJson 响应体
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void event(JSONObject eventJson, HttpServletRequest request, HttpServletResponse response){
        System.out.println("执行该事件对应的业务逻辑");
    }
}
impl服务实现(也就是具体的处理者)

经过使用了策略模式+简单工厂方案后,已经消除了if-else的结构,每当新来了一种回执,只需要添加新的处理业务处理者即可,符合开闭原则

说一下另一种方法比较简单,不需要编写EventFactory 策略工厂:

@RestController
@RequestMapping(value = "/**/server/paycore")
@Api(tags = "G04-PayCoreController",  value= "支付核心回调控制层")
@Slf4j
public class PayCoreController {

    @ApiOperation (value = "G0401-支付核心通知回调", notes = "支付核心通知回调")
    @PostMapping ("/callback")
    public R payCorePayResult(@RequestBody JSONObject eventJson, HttpServletRequest request, HttpServletResponse response) throws Exception{
        String event = eventJson.getString("event").toUpperCase();
        //主要区别在这里
        PayCoreCallbackStrategyService payCoreCallbackStrategy = (PayCoreCallbackStrategyService) SpringContextUtils.getBean(event);
        if (payCoreCallbackStrategy != null){
            payCoreCallbackStrategy.event(eventJson,request,response);
        }else {
            return R.failed("不存在该event事件");
        }
        return R.success();
    }
}
controller层

StrategyService工厂服务以及impl服务实现(也就是具体的处理者)跟上面一样

如有问题还请留言,一起学习讨论共同进步

 

posted @ 2021-10-29 18:08  小巫同学  阅读(202)  评论(0编辑  收藏  举报