SpringMVC | 设计模式实战 ——工厂模式(善用接口与抽象类)

背景故事

接口、抽象类、多态这些JAVA基础中的基础,在多少初级中级攻城狮的眼中如同鸡肋,去掉接口其它两项工作两年没真正去使用过的人不在少数。
随着敏捷模式在国内大肆推广,底层技术人员疲于应付不断变动需求,总在高呼红烧产品,清蒸设计。同时为自己那杂乱无章满是补丁的代码找了一个冠冕堂皇的理由——需求一直在变哪有时间去优化!

推荐一本书 Martin Fowler的《重构:改善既有代码的设计》,我感觉写的棒极了,让我认识到什么是重构,什么时候重构,在什么地方重构。(好像跑题了这些跟工厂模式有个球关系?)

重新回到我们本次的案例需求,就以订单状态变更这个业务来说吧,订单变成任意一个状态其实都有着各自不同的业务需求,可他们又有着一些共同的逻辑,
例如(假想案例而已请勿较真):

  • 订单取消:状态修改、记录日志、冻结库存释放、消息通知
  • 订单支付成功:状态修改、记录日志、冻结库存扣除、消息通知
  • 订单派送中:状态修改、记录日志、消息通知
  • 已签收:状态修改、记录日志、消息通知、增加用户积分、资金划转

代码实现

首先创建一个用于订单状态修改的接口

package com.zhibo.test.service;

public interface OrderStatusService {
    /**
     * 状态变更业务
     * @param orderId 这个参数正常业务肯定是传一个对象了
     */
    void orderStatusChange(String orderId);

    /**
     * 实例所支持的状态类型
     * @return
     */
    String getType();
}

创建一个抽象类用于实现或规范公共的业务流程

主要用于定义整个业务流程线,同时实现部分共用的逻辑代码

package com.zhibo.test.service.impl;

import com.zhibo.test.service.OrderStatusService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service
public abstract class AbstractOrderStatusService implements OrderStatusService {
    protected static Logger log = LoggerFactory.getLogger(AbstractOrderStatusService.class);

    @Override
    public void orderStatusChange(String orderId) {
        verify(orderId);
        Object obj = new Object();
        buildOrder(obj);
        // 公共业务 如组装数据修改订单表参数,插入订单状态变更轨迹...

        try {
            sendMessage(getMessage(null));
        } catch (Exception e) {
            log.error("update loan status push error: ", e);
        }

    }

    // 用于不同的业务流程可能有特定的数据需要组装
    protected void buildOrder(Object obj){}

    // 业务前的校验
    protected void verify(String orderId){}

    protected void sendMessage(Object obj)  throws Exception{
        if (obj !=null){
            // ....调用接口发送消息
        }
    }

    // 根据业务自行组装消息对象
    protected abstract Object getMessage(Object dto);

}

创建不同类型的实例

各个实例只需要关注差异流程进行补充

package com.zhibo.test.service.impl;
import org.springframework.stereotype.Service;

@Service
public class OrderStatusCanceledServiceImpl extends AbstractOrderStatusService{
    @Override
    public String getType() {
        return "canceled";
    }

    @Override
    protected void buildOrder(Object obj) {
    }

    @Override
    protected void verify(String orderId) {
        log.info("订单取消相关数据校验");
    }

    @Override
    protected Object getMessage(Object dto) {
        return null;
    }
}
package com.zhibo.test.service.impl;
import org.springframework.stereotype.Service;

@Service
public class OrderStatusCloseServiceImpl extends AbstractOrderStatusService{
    @Override
    public String getType() {
        return "close";
    }

    @Override
    protected void buildOrder(Object obj) {
        super.buildOrder(obj);
    }

    @Override
    protected void verify(String orderId) {
        log.info("订单关闭相关数据校验");
    }

    @Override
    protected Object getMessage(Object dto) {
        return null;
    }
}
package com.zhibo.test.service.impl;
import org.springframework.stereotype.Service;

@Service
public class OrderStatusTimeoutServiceImpl extends AbstractOrderStatusService{
    @Override
    public String getType() {
        return "timeout";
    }

    @Override
    protected void buildOrder(Object obj) {
        super.buildOrder(obj);
    }

    @Override
    protected void verify(String orderId) {
        log.info("订单超时相关数据校验");
    }

    @Override
    protected Object getMessage(Object dto) {
        return null;
    }
}

创建工厂方法

package com.zhibo.test.method;

import com.zhibo.test.service.OrderStatusService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Component
public class OrderStateMethodConfiguration {

    private Map orderStatusServiceHashMap = new HashMap<>();

    @Autowired
    private List orderStatusServices;

    @PostConstruct
    public void init() {
        orderStatusServices.forEach(orderStatusService ->
                orderStatusServiceHashMap.put(orderStatusService.getType(),orderStatusService));
    }

    public OrderStatusService getLoanStatusService(String orderState){
        return orderStatusServiceHashMap.get(orderState);
    }
}

业务中调用方法

package com.zhibo.test.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class TestService {

    @Autowired
    private OrderStateMethodConfiguration orderStateMethodConfiguration;

    public void test(){
        orderStateMethodConfiguration.getLoanStatusService("timeout").orderStatusChange("123456");
    }
}

输出结果
输出结果
就这么简单,根据业务实际情况来使用抽象类 结合工厂让你的代码变得简洁易懂,且具备良好的扩展性,总比你在一个方法中写着无数的if判断来区分有逼格。

扩展案例:例如微信扫码登录、手机号短信登录、账户密码登录、第三方登录,类似于这种都需要做参数校验,但是不同的登录方式校验的数据会有一些区别,这时候去定义一个参数校验接口,然后去实现它每一个实例去做一种校验,然后根据登录类型将对应的校验方式放入集合中,工厂返回一个service的集合去循环做校验。
下面有部分代码图
SpringMVC | 设计模式实战 ——工厂模式(善用接口与抽象类)_第1张图片SpringMVC | 设计模式实战 ——工厂模式(善用接口与抽象类)_第2张图片

你可能感兴趣的:(工作,-,术)