基于模板方法+协调者委托对现有冗余代码的改造案例
作者:互联网
文章目录
一、背景
当前有一个应用服务,因为本次涉及到产品需求变更,当完成技术方案后,然后看了一下需要涉及变更的代码,发现有一个service及实现类,该实现类提供不同场景的三要素验证逻辑,总体验证逻辑就是先进行业务规则校验,如果检验不通过,则包装返回业务校验信息;如果校验通过,则进行数据库落库,存储当前身份认证信息。
但是基于当前产品需求,无非就是在service增加一个成员方法,然后实现类实现该方法,拷贝一下其他成员方法的业务逻辑,稍微改造一下,然后就实现了产品需求业务逻辑了。但是呢,看着当前这个service类,看到很多成员方法业务逻辑类似,不忍心将就一下,然后就想着怎么更好的思路重构一下现有的代码。
二、分析
我们先来看一下想要重构的代码原样
1、CustomerRelationService
接口代码
public interface CustomerRelationService {
OpenIdRelation getBindedRelationByOpenId(String openId);
/**
* XXX绑定信息
* @param dto
* @return
*/
RespDTO bindCustomer(BindOpenIdRequestDTO bindOpenIdRequestDTO);
/**
* XXX绑定信息
* @param dto
* @return
*/
RespDTO releaseBindCustomer(BindOpenIdRequestDTO dto);
/**
* XXX绑定信息
* @param dto
* @return
*/
RespDTO refundBindOpenId(BindOpenIdRequestDTO dto);
List<OpenIdRelation> queryRecordsByIdno(String idno);
}
2、CustomerRelationServiceImpl
对应实现类:
@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绑定
* @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("短信验证码错误超过%s次,1分钟后再次重试!",totalCount));
}
String verifyCodeFromCache = msgCacheManager.getBindCacheValue(mobile);
log.info("[绑定客户关系 从缓存中获取到到验证码为 verifyCode = {}]", verifyCodeFromCache);
if (verifyCodeFromCache == null || !Objects.equals(verifyCodeFromCache, verifyCode)) {
log.error("[绑定客户关系 验证码匹配失败 openId={}]", openId);
msgCacheManager.recordErrorCount(mobile);
return RespDTO.fail("短信验证码错误,请重新填写");
}
msgCacheManager.clearRecordErrorCount(mobile);
List<MortgageDetailDTO> list = mortgageHttpApi.getMortgageDetailByIdNo(idNo);
if (CollectionUtils.isEmpty(list)) {
return RespDTO.fail("未查询到您的身份信息,请确认无误后重新提交");
}
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("[绑定客户关系 提交信息与系统信息不匹配 openId = {}]", openId);
return RespDTO.fail("未查询到您的身份信息,请确认无误后重新提交");
}
OpenIdRelation isExist = getBindedRelationByOpenId(openId);
if (isExist != null) {
log.error("[绑定客户关系 用户信息已绑定 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();
}
/**
* 校验验证码,错误则返回
* @return
*/
private RespDTO verifyCode(BindOpenIdRequestDTO dto){
String cacheValue = msgCacheManager.getBindCacheValue(dto.getMobile());
return VerifyCodeUtil.verify(cacheValue, dto.getOpenId(), dto.getVerifyCode());
}
/**
* XX绑定信息
* @param dto
* @return
*/
@Override
public RespDTO releaseBindCustomer(BindOpenIdRequestDTO dto) {
//1、校验验证码,错误则返回
RespDTO resp = verifyCode(dto);
if (RespStatusEnum.FAIL.getStatus() == resp.getStatus()){
return resp;
}
//2、从订单中心查询客户信息是否匹配,不存在则返回
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 提交信息与系统信息不匹配 openId = {}]", openId);
return RespDTO.fail("未查询到您的身份信息,请确认无误后重新提交");
}
//3、判断是否已经绑定,绑定则返回
if (null != getBindedRelationByOpenId(openId)) {
log.error("[XXXXX 用户信息已绑定 openId = {}]", openId);
return RespDTO.success();
}
//4、未绑定,则进行绑定
bind(dto);
return RespDTO.success();
}
/**
* XXX绑定
* @param dto
* @return
*/
@Override
public RespDTO refundBindOpenId(BindOpenIdRequestDTO dto) {
//1、校验验证码,错误则返回
RespDTO respDTO = verifyCode(dto);
if (RespStatusEnum.FAIL.getStatus() == respDTO.getStatus()){
return respDTO;
}
//2、从订单中心查询客户信息是否匹配,不存在则返回
String openId = dto.getOpenId();
RespDTO<TransferRefundOrderRe> resp = mortgageHttpApi.queryRefundOrder(dto.getIdNo());
TransferRefundOrderRe refundVO = resp.getData();
if (Objects.isNull(refundVO)){
log.error("[退款绑定客户关系 提交信息与系统信息不匹配 openId = {}]", openId);
return RespDTO.fail("未查询到您的身份信息,请确认无误后重新提交");
}
//3、判断是否已经绑定,绑定则返回
if (null != getBindedRelationByOpenId(openId)) {
log.error("[退款绑定客户关系 用户信息已绑定 openId = {}]", openId);
return RespDTO.success();
}
//4、未绑定,则进行绑定
bind(dto);
return RespDTO.success();
}
@Override
public List<OpenIdRelation> queryRecordsByIdno(String idno) {
List<OpenIdRelation> list = openIdRelationMapper.queryRecordsByIdno(idno);
return list;
}
/**
* 保存绑定数据
* @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()
);
}
}
}
上述类有三个重要的方法如下,上面实现类就是基于下面三种方法的不同场景的业务逻辑实现
RespDTO bindCustomer(BindOpenIdRequestDTO bindOpenIdRequestDTO);
/**
* @param dto
* @return
*/
RespDTO releaseBindCustomer(BindOpenIdRequestDTO dto);
/**
* @param dto
* @return
*/
RespDTO refundBindOpenId(BindOpenIdRequestDTO dto);
总体而言,重构的思路就是通过模板方法定义一个抽象类,然后三个不同的方法就是抽象类的三个不同实现类,相同的代码逻辑(即前置业务校验+绑定)则抽象在抽象类中,对外暴露一个公共方法。
然后通过一个委托代理类,通过上线文对象来封装不同的业务场景类型,然后委托对应的抽象类的实现类来处理业务逻辑,这样以来,如果再增加绑定方法时,只需要增加相应的子类,同事修改某个场景时,也只需要修改对应的子类即可,这样符合开闭原则。
三、重构
1、UML设计
整体设计思路
- 通过定义抽象类
AbstractBindHandler
,把相关三要素场景校验的步骤封装起来,对于子类只需要实现前置校验抽象方法即可。 - 通过定义
BindContext
上下文对象,封装整个流程所依赖的请求参数和输出。 - 通过定义枚举类Biz,然后实现增加响应的
Handler
,只需要在枚举类增加成员即可。 - 通过定义
BindHandlerDispatcher
,实现对Handler
的封装,对于外部业务调用只需要跟BindHandlerDispatcher
交互即可,屏蔽Handler
类的细节。 - 后续如果增加业务场景,只需要增加
Handler
类即可,如果修改对应业务场景,只需要找到对应Handler
类修改即可,即符合开闭原则。
2、BindContext
该类包含三个常用属性,param输出参数,Handler类所依赖的参数通过param传输,该类型是个泛型,需要Handler类来定义声明,Biz是个枚举类。
/**
* @description: 客户绑定上下文对象
* @Date : 2021/10/29 5:52 PM
* @Author : 石冬冬-Seig Heil
*/
@Data
@Builder
public class BindContext<P> {
/**
* DTO参数
*/
private P param;
/**
* 业务类型
*/
private Biz biz;
/**
* 响应报文
*/
private RespDTO respDTO;
/**
* 业务类型
*/
public enum Biz{
/**
* XXX付款客户绑定
*/
ESC_PAYMENT_BIND,
/**
* XXX退款客户绑定
*/
ESC_REFUND_BIND,
/**
* XXX解押客户绑定
*/
ESC_RELEASE_BIND,
/**
* XXX解押客户绑定
*/
CRZ_RELEASE_BIND
}
}
3、AbstractBindHandler
Handler类的基类,依然是个泛型抽象类,需要子类来声明输入参数Param需要继承BindOpenIdRequestDTO。
/**
* @description: 抽象公众号客户三要素绑定处理器
* @Date : 2021/10/29 5:51 PM
* @Author : 石冬冬-Seig Heil
*/
public abstract class AbstractBindHandler<P extends BindOpenIdRequestDTO> {
/**
* 进行绑定的标识
*/
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;
/**
* 前置校验
* @param context 上下文
* @return
*/
abstract RespDTO verify(BindContext<P> context);
/**
* 对外暴露方法
* @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());
}
}
/**
* 保存绑定数据
* @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()
);
}
}
/**
* 根据openId查询已经绑定的关系
* @param openId
* @return
*/
protected OpenIdRelation getBindedRelationByOpenId(String openId) {
return customerRelationService.getBindedRelationByOpenId(openId);
}
/**
* 校验验证码,错误则返回
* @return
*/
RespDTO verifyCode(BindOpenIdRequestDTO dto){
String cacheValue = msgCacheManager.getBindCacheValue(dto.getMobile());
return VerifyCodeUtil.verify(cacheValue, dto.getOpenId(), dto.getVerifyCode());
}
}
相关实现类
CrzReleaseBindHandler
@Service
@Slf4j
public class CrzReleaseBindHandler extends AbstractBindHandler<BindOpenIdRequestDTO>{
@Autowired
MortgageHttpApi mortgageHttpApi;
@Override
RespDTO verify(BindContext<BindOpenIdRequestDTO> context) {
BindOpenIdRequestDTO dto = context.getParam();
//1、校验验证码,错误则返回
RespDTO respDTO = verifyCode(dto);
if (RespStatusEnum.FAIL.getStatus() == respDTO.getStatus()){
return respDTO;
}
MockConfig mockConfig = diamondConfigProxy.mockConfig();
List<String> idnoMockList = mockConfig.getReleaseIdNoMockList();
//身份证白名单 忽略三要素验证
boolean whiteIdno = null != idnoMockList && idnoMockList.contains(dto.getIdNo());
if(!whiteIdno){
//2、身份校验
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、判断是否已经绑定,绑定则返回
String openId = dto.getOpenId();
if (null != getBindedRelationByOpenId(openId)) {
log.error("[退款绑定客户关系 用户信息已绑定 openId = {}]", openId);
return RespDTO.success();
}
return RespDTO.success(BIND_TAG);
}
}
EscPaymentBindHandler
/**
* @description: 二手车付款 客户绑定 处理器
* @Date : 2021/10/29 6:01 PM
* @Author : 石冬冬-Seig Heil
*/
@Service
@Slf4j
public class EscPaymentBindHandler extends AbstractBindHandler<BindOpenIdRequestDTO>{
/**
* 短信验证码错误次数阈值上限
*/
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("短信验证码错误超过%s次,1分钟后再次重试!",totalCount));
}
String verifyCodeFromCache = msgCacheManager.getBindCacheValue(mobile);
log.info("[绑定客户关系 从缓存中获取到到验证码为 verifyCode = {}]", verifyCodeFromCache);
if (verifyCodeFromCache == null || !Objects.equals(verifyCodeFromCache, verifyCode)) {
log.error("[绑定客户关系 验证码匹配失败 openId={}]", openId);
msgCacheManager.recordErrorCount(mobile);
return RespDTO.fail("短信验证码错误,请重新填写");
}
msgCacheManager.clearRecordErrorCount(mobile);
List<MortgageDetailDTO> list = mortgageHttpApi.getMortgageDetailByIdNo(idNo);
if (CollectionUtils.isEmpty(list)) {
return RespDTO.fail("未查询到您的身份信息,请确认无误后重新提交");
}
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("[绑定客户关系 提交信息与系统信息不匹配 openId = {}]", openId);
return RespDTO.fail("未查询到您的身份信息,请确认无误后重新提交");
}
OpenIdRelation isExist = getBindedRelationByOpenId(openId);
if (isExist != null) {
log.error("[绑定客户关系 用户信息已绑定 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: 二手车退款客户绑定 处理器
* @Date : 2021/10/29 6:01 PM
* @Author : 石冬冬-Seig Heil
*/
@Service
@Slf4j
public class EscRefundBindHandler extends AbstractBindHandler<BindOpenIdRequestDTO>{
@Override
RespDTO verify(BindContext<BindOpenIdRequestDTO> context) {
BindOpenIdRequestDTO dto = context.getParam();
//1、校验验证码,错误则返回
RespDTO respDTO = verifyCode(dto);
if (RespStatusEnum.FAIL.getStatus() == respDTO.getStatus()){
return respDTO;
}
//2、从订单中心查询客户信息是否匹配,不存在则返回
String openId = dto.getOpenId();
RespDTO<TransferRefundOrderRe> resp = mortgageHttpApi.queryRefundOrder(dto.getIdNo());
TransferRefundOrderRe refundVO = resp.getData();
if (Objects.isNull(refundVO)){
log.error("[退款绑定客户关系 提交信息与系统信息不匹配 openId = {}]", openId);
return RespDTO.fail("未查询到您的身份信息,请确认无误后重新提交");
}
//3、判断是否已经绑定,绑定则返回
if (null != getBindedRelationByOpenId(openId)) {
log.error("[退款绑定客户关系 用户信息已绑定 openId = {}]", openId);
return RespDTO.success();
}
return RespDTO.success(BIND_TAG);
}
}
EscReleaseBindHandler
/**
* @description: 二手车解押客户绑定 处理器
* @Date : 2021/10/29 6:01 PM
* @Author : 石冬冬-Seig Heil
*/
@Service
@Slf4j
public class EscReleaseBindHandler extends AbstractBindHandler<BindOpenIdRequestDTO>{
@Override
RespDTO verify(BindContext<BindOpenIdRequestDTO> context) {
BindOpenIdRequestDTO dto = context.getParam();
//1、校验验证码,错误则返回
RespDTO resp = verifyCode(dto);
if (RespStatusEnum.FAIL.getStatus() == resp.getStatus()){
return resp;
}
//2、从订单中心查询客户信息是否匹配,不存在则返回
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("[解押绑定客户关系 提交信息与系统信息不匹配 openId = {}]", openId);
return RespDTO.fail("未查询到您的身份信息,请确认无误后重新提交");
}
//3、判断是否已经绑定,绑定则返回
if (null != getBindedRelationByOpenId(openId)) {
log.error("[解押绑定客户关系 用户信息已绑定 openId = {}]", openId);
return RespDTO.success();
}
return RespDTO.success(BIND_TAG);
}
}
4、BindHandlerDispatcher
该类的职责相当于Handler的协调者,它根据context的类型biz,进而指挥对应的Handler类
/**
* @description: 客户关系绑定处理分发器
* @Date : 2021/10/29 6:19 PM
* @Author : 石冬冬-Seig Heil
*/
@Component
public class BindHandlerDispatcher {
@Resource
EscPaymentBindHandler escPaymentBindHandler;
@Resource
EscReleaseBindHandler escReleaseBindHandler;
@Resource
EscRefundBindHandler escRefundBindHandler;
@Resource
CrzReleaseBindHandler crzReleaseBindHandler;
/**
* 根据业务类型分发对应的处理器来处理
* @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
重构后,这里的成员方法只需要构造BindContext实例对象,然后调用Dispatcher.dispatch的成员方法即可,代码这时候看起来清爽许多。
/**
* XX绑定
* @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绑定信息
* @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绑定
* @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绑定
* @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();
}
四、总结
通过重构前后对比,我们发现整个Service类(CustomerRelationServiceImpl
)的的代码这时候通过Handler
类来封装了,而service类中仅仅只需要委托Dispatcher
整个类,通过构造BindContext实例对象,进而调用其dispatch
方法即可。
整个service对外提供的方法并没有做任何改变,后续如果增加成员方法,只需要增加Handler
类即可。
标签:openId,return,绑定,协调者,RespDTO,冗余,context,dto,模板 来源: https://blog.csdn.net/shichen2010/article/details/121288977