记一次使用设计模式简化代码-策略模式+工厂模式

456 阅读4分钟

什么是设计模式?

在软件工程中,软件设计模式(Design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案,这个听起来很高大上的东西,但却与我们程序员息息相关,我们平时用到的框架里面多多少少都会包含设计模式(没吃过猪肉肯定见过猪跑啊🐖🏃)。

我们不能为了使用设计模式而使用设计模式。

我在这个时候选择使用设计模式

接入正题,最近接了一个需求,有个商家端在使用我们产品的时候提了一个需求,就是在操作完成之后,需要把上传数据同步一份到他们那边去。我心想,怎么这么多骚操 - -#,就在上传数据对应的后端接口中加点代码把数据往那边同步就行啦(具体同步的策略这里选的是http回调,为什么选这个略过....)心里已经暗自窃喜。正在我得意的时候,突然机灵一动,现在只是一个商家端需要这样,我只用写一个判断,如果上传用户是该商家端则进行回调操作,那么后续在来几个商家端咋办,我要在哪里无限写if-else吗,而且每个商家端的需求可能还不一样,下一个可能是不仅要回调还要求回调之前在对数据进行特殊处理等等。那我的代码最终不就变成了这样:

        /*上面为正常的上传数据的逻辑操作略。。。*/
        try {
            if(CLIENT_A.equals(channel)){
                client_A_service.doSomething();
            }else if(CLIENT_B.equals(channel)){
                client_B_service.doSomething();
            }else if(CLIENT_C.equals(channel)){
                client_C_service.doSomething();
            }else if(CLIENT_D.equals(channel)){
                client_D_service.doSomething();
            }else if(CLIENT_E.equals(channel)){
                client_E_service.doSomething();
            }else if(CLIENT_F.equals(channel)){
                client_F_service.doSomething();
            }else if(CLIENT_G.equals(channel)){
                client_G_service.doSomething();
            }
        }catch (Exception e){
            /*处理商家端定制逻辑失败的情况略。。。*/
        }

这是我不能接受的啊,因为老师教过我们如果你的代码中if-else过多,你这代码就是裹脚布(又臭又长)。。这肯定有办法解决的。

thinking...... two minutes later......

这里不是用工厂策略模式就可以完美解决!

1.首先定义一个工厂,这个工厂主要用来生成商家端处理逻辑的对象

/**
 * 商家端处理逻辑
 *
 * @author orange
 */
@Service
public class BusinessClientServiceFactory {

    /**
     * 用来存放具体具体商家端的Map
     */
    private final Map<String, BusinessClientService> clientMap = new HashMap<>();

    /**
     * 商家端字典配置
     */
    @Autowired
    private ClientDictMapper clientDictMapper;

    /**
     * 商家端具体处理方法
     *
     */
    public BaseResult doSomething(String channel) {
        return getClient(channel).doSomething(channel);
    }

    /**
     * 根据渠道获取一个商家端
     * @param channel 渠道
     * @return
     */
    private BusinessClientService getClient(String channel) {
        BusinessClientService service = clientMap.get(channel);
        if(service != null){
              return service;
        }
        throw new ClientNotFoundException("当前客户端不存在");
    }

    /**
     * 注册商家端到工厂
     * @param channel 渠道
     * @param businessClientService 商家端处理service
     */
    public void addClient(String channel, BusinessClientService businessClientService) {
        clientMap.put(channel, businessClientService);
    }

    /**
     * 获取商家端配置信息
     * @param channel 渠道
     * @return
     */
    public String getCallBackUrl(String channel){
        ClientDictPo clientDictPo = clientDictMapper.findOneByTypeAndChannel(DictEnum.CALL_BACK_URL.getType(), channel);
        return clientDictPo != null ? clientDictPo.getDictValue() :null;
    }
}

2.需要定义商家端的处理业务的service接口

/**
 * 处理商家端业务
 * @author orange
 */
public interface BusinessClientService {
    /**
     * 商家端处理自己定制需求的方法
     * @param channel  渠道
     * @return 返回信息
     *
     */
    BaseResult doSomething(String channel);
}

3.修改调用地方的逻辑

    @Resource
    private BusinessClientServiceFactory clientServiceFactory;
    
    public void upload(String channel){
        /*上面为正常的上传数据的逻辑操作略。。。*/
        try {
            //单独处理商家端的定制逻辑
            clientServiceFactory.doSomething(channel);
        }catch (Exception e){
            /*处理商家端定制逻辑失败的情况略。。。*/
        }
    }

4.去实现每一个商家端的自有逻辑

/**
 * @author orange
 */
@Service
public class ClientA implements BusinessClientService{

    @Resource
    BusinessClientServiceFactory factory;

    /**
     * 将次商家端服务添加到工厂中
     */
    @PostConstruct
    public void addClient() {
        factory.addClient(CLIENT_A, this);
    }

    /**
     * 具体逻辑处理方法
     * @param channel 渠道
     * @return 处理结果
     */
    @Override
    public BaseResult doSomething(String channel) {
        String callBackUrl = factory.getCallBackUrl(channel);
        /* 处理所有商家端自由的定制逻辑 */
        /* ...略 */
        return null;
    }
}
/**
 * @author orange
 */
@Service
public class ClientB implements BusinessClientService{

    @Resource
    BusinessClientServiceFactory factory;

    /**
     * 将次商家端服务添加到工厂中
     */
    @PostConstruct
    public void addClient() {
        factory.addClient(CLIENT_B, this);
    }

    /**
     * 具体逻辑处理方法
     * @param channel 渠道
     * @return 处理结果
     */
    @Override
    public BaseResult doSomething(String channel) {
        String callBackUrl = factory.getCallBackUrl(channel);
        /* 处理所有商家端自由的定制逻辑 */
        /* ...略 */
        return null;
    }
}

....

到这里就基本大功告成!后续如果接入新的商家端只用新增类去实现商家端特有逻辑即可,其他的地方都不需要修改了,是不是很简洁舒适相对于之前长长的if-else来说。

##结语: 这是我第一次写博客文章,很激动,构思了很久,本来想写一些科普介绍类的,但是心想这类文章很多,没有特色,于是就把自己最近工作中遇到的一个实际问题记录了上来,其实对于我来说写这个文章的过程也是一个反思进步的过程,我觉得效果很多,我以后会多多坚持写下去的(虽然我写的可能比较烂.....哈哈哈哈哈哈哈)!

ps:如果上述内容有什么问题,引起大家不适,勿语,反正我不会改😼😼😼😼😼

ps2.0:补充类图一张