Modification case of existing redundant code entrusted by template method + Coordinator

1, Background

At present, there is an application service because it involves product demand change. After completing the technical scheme, I looked at the code that needs to be changed and found that there is a service and implementation class. The implementation class provides three element verification logic for different scenarios. The overall verification logic is to verify the business rules first. If the verification fails, Then the package returns the business verification information; If the verification is passed, the database will be dropped and the current identity authentication information will be stored.

However, based on the current product requirements, it is nothing more than adding a member method to the service, then implementing the method by the class, copying the business logic of other member methods, making a slight transformation, and then implementing the product requirements business logic. However, looking at the current service class, I see that many member methods have similar business logic. I can't bear to make do with it, and then I think about how to better reconstruct the existing code.

2, Analysis

Let's take a look at the original code we want to refactor

1,CustomerRelationService

Interface code

public interface CustomerRelationService {
    OpenIdRelation getBindedRelationByOpenId(String openId);
		/**
     * XXX Binding information
     * @param dto
     * @return
     */
    RespDTO bindCustomer(BindOpenIdRequestDTO bindOpenIdRequestDTO);

    /**
     * XXX Binding information
     * @param dto
     * @return
     */
    RespDTO releaseBindCustomer(BindOpenIdRequestDTO dto);
    /**
     * XXX Binding information
     * @param dto
     * @return
     */
    RespDTO refundBindOpenId(BindOpenIdRequestDTO dto);

    List<OpenIdRelation> queryRecordsByIdno(String idno);
}

2,CustomerRelationServiceImpl

Corresponding implementation class:

@Service
@Slf4j
public class CustomerRelationServiceImpl implements CustomerRelationService {

    private static final String OPEN_ID = "openId";

    private static final String STATUS = "status";

    private static final int STATUS_BINDED = 0;

    static final int UPPER_LIMIT_ERROR_COUNT = 10;

    @Autowired
    private OpenIdRelationMapper openIdRelationMapper;

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private MortgageService mortgageService;

    @Autowired
    MsgCacheManager msgCacheManager;

    @Autowired
    OrderCenterHttpApi orderCenterHttpApi;

    @Autowired
    MortgageHttpApi mortgageHttpApi;

    @Override
    public OpenIdRelation getBindedRelationByOpenId(String openId) {
        Map<String, Object> param = Maps.newHashMap();
        param.put(OPEN_ID, openId);
        param.put(STATUS, STATUS_BINDED);
        OpenIdRelation openIdRelation = openIdRelationMapper.selectByParam(param);
        return Optional.ofNullable(openIdRelation).orElse(null);
    }

    /**
     * XX binding
     * @param verifyCode
     * @param mobile
     * @param idNo
     * @param realName
     * @param openId
     * @return
     */
    @Override
    public RespDTO bindCustomer(String verifyCode, String mobile, String idNo, String realName, String openId) {
        long totalCount = msgCacheManager.getRecordErrorCount(mobile);
        if(totalCount >= UPPER_LIMIT_ERROR_COUNT){
            return RespDTO.fail(String.format("SMS verification code error exceeds%s Times, try again in 1 minute!",totalCount));
        }
        String verifyCodeFromCache = msgCacheManager.getBindCacheValue(mobile);
        log.info("[The binding customer relationship obtains the verification code from the cache verifyCode = {}]", verifyCodeFromCache);
        if (verifyCodeFromCache == null || !Objects.equals(verifyCodeFromCache, verifyCode)) {
            log.error("[Binding customer relationship verification code matching failed openId={}]", openId);
            msgCacheManager.recordErrorCount(mobile);
            return RespDTO.fail("SMS verification code error, please fill in again");
        }
        msgCacheManager.clearRecordErrorCount(mobile);
        List<MortgageDetailDTO> list = mortgageHttpApi.getMortgageDetailByIdNo(idNo);
        if (CollectionUtils.isEmpty(list)) {
            return RespDTO.fail("Your identity information was not found. Please re submit it after confirmation");
        }
        MortgageDetailDTO mortgageDetailDTO = list.stream()
                .filter(mortgageDetail-> Objects.equals(mortgageDetail.getApiCustomerVO().getCustomerMobile(), mobile)
                        && Objects.equals(mortgageDetail.getApiCustomerVO().getCustomerName(), realName)).findFirst().orElse(null);
        if (ObjectUtils.isEmpty(mortgageDetailDTO)) {
            log.error("[The binding customer relationship submission information does not match the system information openId = {}]", openId);
            return RespDTO.fail("Your identity information was not found. Please re submit it after confirmation");
        }
        OpenIdRelation isExist = getBindedRelationByOpenId(openId);
        if (isExist != null) {
            log.error("[Binding customer relationship user information bound openId = {}]", openId);
            return RespDTO.success();
        }

        Customer customer = Customer.builder().idno(idNo).realName(realName).mobile(mobile).build();
        long insertCount = customerMapper.insertSelective(customer);
        if (insertCount != 0) {
            OpenIdRelation openIdRelation = OpenIdRelation.builder().customerId(customer.getId()).openId(openId).idNo(idNo).status(OpenIdRelation.BIND_STATUS)
                    .bindTime(new Date()).build();
            openIdRelationMapper.insertSelective(openIdRelation);
        }

        return RespDTO.success();
    }


    /**
     * Verify the verification code, and return if there is an error
     * @return
     */
    private RespDTO verifyCode(BindOpenIdRequestDTO dto){
        String cacheValue = msgCacheManager.getBindCacheValue(dto.getMobile());
        return VerifyCodeUtil.verify(cacheValue, dto.getOpenId(), dto.getVerifyCode());
    }

    /**
     * XX Binding information
     * @param dto
     * @return
     */
    @Override
    public RespDTO releaseBindCustomer(BindOpenIdRequestDTO dto) {
        //1. Verify the verification code, and return if there is an error
        RespDTO resp = verifyCode(dto);
        if (RespStatusEnum.FAIL.getStatus() == resp.getStatus()){
            return resp;
        }

        //2. Query whether the customer information matches from the order center. If it does not exist, return
        String idNo = dto.getIdNo();
        String openId = dto.getOpenId();
        List<OrderDetailVO> list = orderCenterHttpApi.queryOrderInfoByIdNo(idNo);
        OrderDetailVO detailVO = list.stream().filter(o -> Objects.nonNull(o.getApplicantDetailVO())
                && Objects.equals(dto.getRealName(), o.getApplicantDetailVO().getName())
                && (Objects.equals(dto.getMobile(), o.getApplicantDetailVO().getMobile())
                    || Objects.equals(dto.getMobile(), o.getApplicantDetailVO().getMobile2()))).findAny().orElse(null);
        if (Objects.isNull(detailVO)){
            log.error("[XXXXX The submitted information does not match the system information openId = {}]", openId);
            return RespDTO.fail("Your identity information was not found. Please re submit it after confirmation");
        }

        //3. Judge whether it has been bound, and return
        if (null != getBindedRelationByOpenId(openId)) {
            log.error("[XXXXX User information bound openId = {}]", openId);
            return RespDTO.success();
        }

        //4. If not bound, bind
        bind(dto);
        return RespDTO.success();
    }

    /**
     * XXX binding
     * @param dto
     * @return
     */
    @Override
    public RespDTO refundBindOpenId(BindOpenIdRequestDTO dto) {
        //1. Verify the verification code, and return if there is an error
        RespDTO respDTO = verifyCode(dto);
        if (RespStatusEnum.FAIL.getStatus() == respDTO.getStatus()){
            return respDTO;
        }

        //2. Query whether the customer information matches from the order center. If it does not exist, return
        String openId = dto.getOpenId();
        RespDTO<TransferRefundOrderRe> resp = mortgageHttpApi.queryRefundOrder(dto.getIdNo());
        TransferRefundOrderRe refundVO = resp.getData();
        if (Objects.isNull(refundVO)){
            log.error("[The refund binding customer relationship submission information does not match the system information openId = {}]", openId);
            return RespDTO.fail("Your identity information was not found. Please re submit it after confirmation");
        }

        //3. Judge whether it has been bound, and return
        if (null != getBindedRelationByOpenId(openId)) {
            log.error("[Refund binding customer relationship user information bound openId = {}]", openId);
            return RespDTO.success();
        }

        //4. If not bound, bind
        bind(dto);
        return RespDTO.success();
    }

    @Override
    public List<OpenIdRelation> queryRecordsByIdno(String idno) {
        List<OpenIdRelation> list = openIdRelationMapper.queryRecordsByIdno(idno);
        return list;
    }

    /**
     * Save binding data
     * @param dto
     */
    private void bind(BindOpenIdRequestDTO dto){
        Customer customer = Customer.builder().idno(dto.getIdNo()).realName(dto.getRealName()).mobile(dto.getMobile()).build();
        long insertCount = customerMapper.insertSelective(customer);
        if (insertCount != 0) {
            openIdRelationMapper.insertSelective(
                    OpenIdRelation.builder()
                            .customerId(customer.getId()).openId(dto.getOpenId()).idNo(dto.getIdNo())
                            .status(OpenIdRelation.BIND_STATUS).bindTime(new Date()).build()
            );
        }
    }
}

The above classes have three important methods as follows. The above implementation class is the business logic implementation based on different scenarios of the following three methods

RespDTO bindCustomer(BindOpenIdRequestDTO bindOpenIdRequestDTO);

/**
 * @param dto
 * @return
 */
RespDTO releaseBindCustomer(BindOpenIdRequestDTO dto);
/**
 * @param dto
 * @return
 */
RespDTO refundBindOpenId(BindOpenIdRequestDTO dto);

Generally speaking, the idea of refactoring is to define an abstract class through the template method, and then three different methods are three different implementation classes of the abstract class. The same code logic (i.e. pre business verification + binding) is abstracted in the abstract class to expose a public method.

Then, a principal-agent class is used to encapsulate different business scenario types through online text objects, and then the implementation class of the corresponding abstract class is entrusted to process business logic. In this way, if you add binding methods, you only need to add corresponding subclasses. When colleagues modify a scenario, you only need to modify the corresponding subclasses, which is in line with the opening and closing principle.

3, Reconstruction

1. UML design

Overall design idea

  • By defining the abstract class AbstractBindHandler, the steps of relevant three element scenario verification are encapsulated. For subclasses, only the pre verification abstract method needs to be implemented.
  • The BindContext context object is defined to encapsulate the request parameters and output that the whole process depends on.
  • Define the enumeration class Biz, and then implement the Handler to add the response. You only need to add members in the enumeration class.
  • The Handler is encapsulated by defining BindHandlerDispatcher. For external business calls, you only need to interact with BindHandlerDispatcher to shield the details of the Handler class.
  • If you add a business scenario later, you only need to add a Handler class. If you modify the corresponding business scenario, you only need to find the corresponding Handler class and modify it, that is, it complies with the opening and closing principle.

2,BindContext

This class contains three common attributes, param output parameters. The parameters that the Handler class depends on are transmitted through param. This type is a generic type and requires the Handler class to define the declaration. Biz is an enumeration class.

/**
 * @description: Client binding context object
 * @Date : 2021/10/29 5:52 PM
 * @Author : Shi Dongdong Seig Heil
 */
@Data
@Builder
public class BindContext<P> {
    /**
     * DTO parameter
     */
    private P param;
    /**
     * Business type
     */
    private Biz biz;
    /**
     * response message
     */
    private RespDTO respDTO;

    /**
     * Business type
     */
    public enum Biz{
        /**
         * XXX Payment customer binding
         */
        ESC_PAYMENT_BIND,
        /**
         * XXX Refund customer binding
         */
        ESC_REFUND_BIND,
        /**
         * XXX Debarred customer binding
         */
        ESC_RELEASE_BIND,
        /**
         * XXX Debarred customer binding
         */
        CRZ_RELEASE_BIND
    }
}

3,AbstractBindHandler

The base class of the Handler class is still a generic abstract class. Subclasses are required to declare the input parameter Param and inherit BindOpenIdRequestDTO.

/**
 * @description: Abstract official account customer three factor binding processor
 * @Date : 2021/10/29 5:51 PM
 * @Author : Shi Dongdong Seig Heil
 */
public abstract class AbstractBindHandler<P extends BindOpenIdRequestDTO> {
    /**
     * Identification of the binding
     */
    final String BIND_TAG = "BIND";

    @Autowired
    DiamondConfigProxy diamondConfigProxy;

    @Autowired
    OpenIdRelationMapper openIdRelationMapper;

    @Autowired
    CustomerMapper customerMapper;

    @Resource
    CustomerRelationService customerRelationService;

    @Autowired
    MortgageService mortgageService;

    @Autowired
    MsgCacheManager msgCacheManager;

    @Autowired
    OrderCenterHttpApi orderCenterHttpApi;

    @Autowired
    MortgageHttpApi mortgageHttpApi;
    /**
     * Pre check
     * @param context context
     * @return
     */
    abstract RespDTO verify(BindContext<P> context);

    /**
     * External exposure method
     * @param context
     */
    public void handle(BindContext<P> context){
        RespDTO respDTO = verify(context);
        context.setRespDTO(respDTO);
        boolean canBind = respDTO.getStatus() ==  RespStatusEnum.SUCCESS.getStatus() && BIND_TAG.equals(respDTO.getData());
        if(canBind){
            bind(context.getParam());
            context.setRespDTO(RespDTO.success());
        }
    }


    /**
     * Save binding data
     * @param dto
     */
    private void bind(BindOpenIdRequestDTO dto){
        Customer customer = Customer.builder().idno(dto.getIdNo()).realName(dto.getRealName()).mobile(dto.getMobile()).build();
        long insertCount = customerMapper.insertSelective(customer);
        if (insertCount != 0) {
            openIdRelationMapper.insertSelective(
                    OpenIdRelation.builder()
                            .customerId(customer.getId()).openId(dto.getOpenId()).idNo(dto.getIdNo())
                            .status(OpenIdRelation.BIND_STATUS).bindTime(new Date()).build()
            );
        }
    }

    /**
     * Query the bound relationship according to openId
     * @param openId
     * @return
     */
    protected OpenIdRelation getBindedRelationByOpenId(String openId) {
        return customerRelationService.getBindedRelationByOpenId(openId);
    }

    /**
     * Verify the verification code, and return if there is an error
     * @return
     */
    RespDTO verifyCode(BindOpenIdRequestDTO dto){
        String cacheValue = msgCacheManager.getBindCacheValue(dto.getMobile());
        return VerifyCodeUtil.verify(cacheValue, dto.getOpenId(), dto.getVerifyCode());
    }
}

Related implementation classes

CrzReleaseBindHandler

@Service
@Slf4j
public class CrzReleaseBindHandler extends AbstractBindHandler<BindOpenIdRequestDTO>{

    @Autowired
    MortgageHttpApi mortgageHttpApi;

    @Override
    RespDTO verify(BindContext<BindOpenIdRequestDTO> context) {
        BindOpenIdRequestDTO dto = context.getParam();
        //1. Verify the verification code, and return if there is an error
        RespDTO respDTO = verifyCode(dto);
        if (RespStatusEnum.FAIL.getStatus() == respDTO.getStatus()){
            return respDTO;
        }
        MockConfig mockConfig = diamondConfigProxy.mockConfig();
        List<String> idnoMockList = mockConfig.getReleaseIdNoMockList();
        //ID card white list ignores three elements verification
        boolean whiteIdno = null != idnoMockList && idnoMockList.contains(dto.getIdNo());
        if(!whiteIdno){
            //2. Identity verification
            CrzReleaseBindVerifyDTO bindVerifyDTO = CrzReleaseBindVerifyDTO.builder()
                    .customerIdno(dto.getIdNo()).customerMobile(dto.getMobile()).customerName(dto.getRealName())
                    .build();
            try {
                RespDTO<String> bindResult = mortgageHttpApi.bindVerify(bindVerifyDTO);
            } catch (InvokeException e) {
                log.error("[CrzReleaseBindHandler#verify]",e);
                return RespDTO.fail(e.getErrMsg());
            }
        }
        //2. Judge whether it has been bound, and return
        String openId = dto.getOpenId();
        if (null != getBindedRelationByOpenId(openId)) {
            log.error("[Refund binding customer relationship user information bound openId = {}]", openId);
            return RespDTO.success();
        }
        return RespDTO.success(BIND_TAG);
    }
}

EscPaymentBindHandler

/**
 * @description: Used car payment customer binding processor
 * @Date : 2021/10/29 6:01 PM
 * @Author : Shi Dongdong Seig Heil
 */
@Service
@Slf4j
public class EscPaymentBindHandler extends AbstractBindHandler<BindOpenIdRequestDTO>{
    /**
     * Upper threshold limit of error times of SMS verification code
     */
    final int UPPER_LIMIT_ERROR_COUNT = 10;

    @Override
    RespDTO verify(BindContext<BindOpenIdRequestDTO> context) {
        BindOpenIdRequestDTO dto = context.getParam();
        String verifyCode = dto.getVerifyCode(), mobile = dto.getMobile(), idNo = dto.getIdNo(), realName = dto.getRealName(), openId = dto.getOpenId();
        long totalCount = msgCacheManager.getRecordErrorCount(mobile);
        if(totalCount >= UPPER_LIMIT_ERROR_COUNT){
            return RespDTO.fail(String.format("SMS verification code error exceeds%s Times, try again in 1 minute!",totalCount));
        }
        String verifyCodeFromCache = msgCacheManager.getBindCacheValue(mobile);
        log.info("[The binding customer relationship obtains the verification code from the cache verifyCode = {}]", verifyCodeFromCache);
        if (verifyCodeFromCache == null || !Objects.equals(verifyCodeFromCache, verifyCode)) {
            log.error("[Binding customer relationship verification code matching failed openId={}]", openId);
            msgCacheManager.recordErrorCount(mobile);
            return RespDTO.fail("SMS verification code error, please fill in again");
        }
        msgCacheManager.clearRecordErrorCount(mobile);
        List<MortgageDetailDTO> list = mortgageHttpApi.getMortgageDetailByIdNo(idNo);
        if (CollectionUtils.isEmpty(list)) {
            return RespDTO.fail("Your identity information was not found. Please re submit it after confirmation");
        }
        MortgageDetailDTO mortgageDetailDTO = list.stream()
                .filter(mortgageDetail-> Objects.equals(mortgageDetail.getApiCustomerVO().getCustomerMobile(), mobile)
                        && Objects.equals(mortgageDetail.getApiCustomerVO().getCustomerName(), realName)).findFirst().orElse(null);
        if (ObjectUtils.isEmpty(mortgageDetailDTO)) {
            log.error("[The binding customer relationship submission information does not match the system information openId = {}]", openId);
            return RespDTO.fail("Your identity information was not found. Please re submit it after confirmation");
        }
        OpenIdRelation isExist = getBindedRelationByOpenId(openId);
        if (isExist != null) {
            log.error("[Binding customer relationship user information bound openId = {}]", openId);
            return RespDTO.success();
        }

        Customer customer = Customer.builder().idno(idNo).realName(realName).mobile(mobile).build();
        long insertCount = customerMapper.insertSelective(customer);
        if (insertCount != 0) {
            OpenIdRelation openIdRelation = OpenIdRelation.builder().customerId(customer.getId()).openId(openId).idNo(idNo).status(OpenIdRelation.BIND_STATUS)
                    .bindTime(new Date()).build();
            openIdRelationMapper.insertSelective(openIdRelation);
        }

        return RespDTO.success(BIND_TAG);
    }
}

EscRefundBindHandler

/**
 * @description: Used car refund customer binding processor
 * @Date : 2021/10/29 6:01 PM
 * @Author : Shi Dongdong Seig Heil
 */
@Service
@Slf4j
public class EscRefundBindHandler extends AbstractBindHandler<BindOpenIdRequestDTO>{

    @Override
    RespDTO verify(BindContext<BindOpenIdRequestDTO> context) {
        BindOpenIdRequestDTO dto = context.getParam();
        //1. Verify the verification code, and return if there is an error
        RespDTO respDTO = verifyCode(dto);
        if (RespStatusEnum.FAIL.getStatus() == respDTO.getStatus()){
            return respDTO;
        }

        //2. Query whether the customer information matches from the order center. If it does not exist, return
        String openId = dto.getOpenId();
        RespDTO<TransferRefundOrderRe> resp = mortgageHttpApi.queryRefundOrder(dto.getIdNo());
        TransferRefundOrderRe refundVO = resp.getData();
        if (Objects.isNull(refundVO)){
            log.error("[The refund binding customer relationship submission information does not match the system information openId = {}]", openId);
            return RespDTO.fail("Your identity information was not found. Please re submit it after confirmation");
        }

        //3. Judge whether it has been bound, and return
        if (null != getBindedRelationByOpenId(openId)) {
            log.error("[Refund binding customer relationship user information bound openId = {}]", openId);
            return RespDTO.success();
        }
        return RespDTO.success(BIND_TAG);
    }
}

EscReleaseBindHandler

/**
 * @description: Used car release customer binding processor
 * @Date : 2021/10/29 6:01 PM
 * @Author : Shi Dongdong Seig Heil
 */
@Service
@Slf4j
public class EscReleaseBindHandler extends AbstractBindHandler<BindOpenIdRequestDTO>{

    @Override
    RespDTO verify(BindContext<BindOpenIdRequestDTO> context) {
        BindOpenIdRequestDTO dto = context.getParam();
        //1. Verify the verification code, and return if there is an error
        RespDTO resp = verifyCode(dto);
        if (RespStatusEnum.FAIL.getStatus() == resp.getStatus()){
            return resp;
        }

        //2. Query whether the customer information matches from the order center. If it does not exist, return
        String idNo = dto.getIdNo();
        String openId = dto.getOpenId();
        List<OrderDetailVO> list = orderCenterHttpApi.queryOrderInfoByIdNo(idNo);
        OrderDetailVO detailVO = list.stream().filter(o -> Objects.nonNull(o.getApplicantDetailVO())
                && Objects.equals(dto.getRealName(), o.getApplicantDetailVO().getName())
                && (Objects.equals(dto.getMobile(), o.getApplicantDetailVO().getMobile())
                || Objects.equals(dto.getMobile(), o.getApplicantDetailVO().getMobile2()))).findAny().orElse(null);
        if (Objects.isNull(detailVO)){
            log.error("[The submitted information of the customer relationship for de pledge binding does not match the system information openId = {}]", openId);
            return RespDTO.fail("Your identity information was not found. Please re submit it after confirmation");
        }

        //3. Judge whether it has been bound, and return
        if (null != getBindedRelationByOpenId(openId)) {
            log.error("[The customer relationship user information has been bound openId = {}]", openId);
            return RespDTO.success();
        }
        return RespDTO.success(BIND_TAG);
    }
}

4,BindHandlerDispatcher

The responsibility of this class is equivalent to the coordinator of the Handler. It commands the corresponding Handler class according to the type biz of the context

/**
 * @description: Customer relationship binding processing distributor
 * @Date : 2021/10/29 6:19 PM
 * @Author : Shi Dongdong Seig Heil
 */
@Component
public class BindHandlerDispatcher {

    @Resource
    EscPaymentBindHandler escPaymentBindHandler;

    @Resource
    EscReleaseBindHandler escReleaseBindHandler;

    @Resource
    EscRefundBindHandler escRefundBindHandler;

    @Resource
    CrzReleaseBindHandler crzReleaseBindHandler;

    /**
     * Distribute the corresponding processor according to the service type for processing
     * @param context
     */
    public void dispatch(BindContext context){
        switch (context.getBiz()){
            case ESC_PAYMENT_BIND:
                escPaymentBindHandler.handle(context);
                return;
            case ESC_REFUND_BIND:
                escRefundBindHandler.handle(context);
                return;
            case ESC_RELEASE_BIND:
                escReleaseBindHandler.handle(context);
                return;
            case CRZ_RELEASE_BIND:
                crzReleaseBindHandler.handle(context);
                return;
        }
    }
}

5,CustomerRelationServiceImpl

After refactoring, the member method here only needs to construct the BindContext instance object and then call the member method of Dispatcher.dispatch. The code at this time looks refreshing.

/**
 * XX binding
 * @param dto
 * @return
 */
@Override
public RespDTO bindCustomer(BindOpenIdRequestDTO dto) {
    BindContext<BindOpenIdRequestDTO> context = BindContext.<BindOpenIdRequestDTO>builder().biz(BindContext.Biz.ESC_PAYMENT_BIND).param(dto).build();
    bindHandlerDispatcher.dispatch(context);
    return context.getRespDTO();
}

/**
 * XX Binding information
 * @param dto
 * @return
 */
@Override
public RespDTO releaseBindCustomer(BindOpenIdRequestDTO dto) {
    BindContext<BindOpenIdRequestDTO> context = BindContext.<BindOpenIdRequestDTO>builder().biz(BindContext.Biz.ESC_RELEASE_BIND).param(dto).build();
    bindHandlerDispatcher.dispatch(context);
    return context.getRespDTO();
}

/**
 * XX binding
 * @param dto
 * @return
 */
@Override
public RespDTO releaseBindCustomerForCrz(BindOpenIdRequestDTO dto) {
    BindContext<BindOpenIdRequestDTO> context = BindContext.<BindOpenIdRequestDTO>builder().biz(BindContext.Biz.CRZ_RELEASE_BIND).param(dto).build();
    bindHandlerDispatcher.dispatch(context);
    return context.getRespDTO();
}

/**
 * XX binding
 * @param dto
 * @return
 */
@Override
public RespDTO refundBindOpenId(BindOpenIdRequestDTO dto) {
    BindContext<BindOpenIdRequestDTO> context = BindContext.<BindOpenIdRequestDTO>builder().biz(BindContext.Biz.ESC_REFUND_BIND).param(dto).build();
    bindHandlerDispatcher.dispatch(context);
    return context.getRespDTO();
}

4, Summary

Through the comparison before and after reconstruction, we find that the code of the whole service class (CustomerRelationServiceImpl) is encapsulated by the Handler class, while the service class only needs to delegate the whole Dispatcher class, construct the BindContext instance object, and then call its dispatch method.

The external methods provided by the whole service have not been changed. If you add member methods later, you only need to add the Handler class.

Tags: Java

Posted on Fri, 12 Nov 2021 06:58:57 -0500 by helbom