数据人与超自然意识 发表于 2024-12-17 21:10:15

项目中的《访问者模式》

这个模式焦点头脑是将基本的数据对象和对应的操作相互分离。数据对象就只是数据对象,如果想要扩展操作,就扩展对应的visitor。
这种模式下的两次分派

第一次分派,是将对数据对象本身举行分派,可以有差别的实现。
第二次分派,是visitor接收差别的数据对象。
结果就是数据对象接受了visitor,然后visitor中组合了数据对象。
这个项目中的使用场景

对于订单状态,有两个数据载体,一个是数据库已存在的当前的状态,一个是消息推送过来的状态。通过两个载体的状态的组合,能做出响应的动作。
处置惩罚逻辑如下⬇︎⬇︎⬇︎
https://img2024.cnblogs.com/blog/3019051/202412/3019051-20241217214335400-64271111.png
UML是如许的⬇︎⬇︎⬇︎
https://img2024.cnblogs.com/blog/3019051/202412/3019051-20241217214416779-1892453250.png
现实代码是如许的⬇︎⬇︎⬇︎
DbStatuspackage com.xxx.sales.saicorder.outerapp.tmall.message.visitor;

import com.xxx.sales.saicorder.outerapp.tmall.enums.BusinessStatusEnum;
import com.xxx.sales.saicorder.outerapp.tmall.enums.MessageDealWithResultEnum;

/**
* @author Euler
*/
public abstract class DbStatus {
    /**
   * 处理结果
   */
    private Integer businessStatus;

    public DbStatus(Integer businessStatus) {
      this.businessStatus = businessStatus;
    }

    private DbStatus() {
    }

    /**
   * 接收天猫状态的visitor
   * @param tmallVisitorStatus
   * @return
   */
    public abstract MessageDealWithResultEnum acceptTmallVisitor(TmallVisitorStatus tmallVisitorStatus);


    /**
   * 将DB记录的处理结果转成BusinessStatusEnum
   * @return
   */
    protected BusinessStatusEnum getBusinessStatus(){
      return BusinessStatusEnum.valueOfCode(businessStatus);
    }
}DbPayedStatuspackage com.xxx.sales.saicorder.outerapp.tmall.message.visitor;

import com.xxx.sales.saicorder.outerapp.tmall.enums.MessageDealWithResultEnum;

/**
* db记录已支付
* @author Euler
*/
public class DbPayedStatus extends DbStatus{


    public DbPayedStatus(Integer businessStatus) {
      super(businessStatus);
    }

    /**
   * 接收天猫状态的visitor
   *
   * @param tmallVisitorStatus
   *
   * @return
   */
    @Override
    public MessageDealWithResultEnum acceptTmallVisitor(TmallVisitorStatus tmallVisitorStatus) {
      return tmallVisitorStatus.visitDbStatus(this);
    }
}DbCloseStatuspackage com.xxx.sales.saicorder.outerapp.tmall.message.visitor;

import com.xxx.sales.saicorder.outerapp.tmall.enums.MessageDealWithResultEnum;

/**
* db记录已关闭
* @author Euler
*/
public class DbCloseStatus extends DbStatus{
    public DbCloseStatus(Integer businessStatus) {
      super(businessStatus);
    }

    /**
   * 接收天猫状态的visitor
   *
   * @param tmallVisitorStatus
   *
   * @return
   */
    @Override
    public MessageDealWithResultEnum acceptTmallVisitor(TmallVisitorStatus tmallVisitorStatus) {
      return tmallVisitorStatus.visitDbStatus(this);
    }
}DbChargeOffStatuspackage com.xxx.sales.saicorder.outerapp.tmall.message.visitor;

import com.xxx.sales.saicorder.outerapp.tmall.enums.MessageDealWithResultEnum;

/**
* db记录已核销
* @author Euler
*/
public class DbChargeOffStatus extends DbStatus{

    public DbChargeOffStatus(Integer businessStatus) {
      super(businessStatus);
    }

    /**
   * 接收天猫状态的visitor
   *
   * @param tmallVisitorStatus
   *
   * @return
   */
    @Override
    public MessageDealWithResultEnum acceptTmallVisitor(TmallVisitorStatus tmallVisitorStatus) {
      return tmallVisitorStatus.visitDbStatus(this);
    }

}TmallVisitorStatuspackage com.xxx.sales.saicorder.outerapp.tmall.message.visitor;

import com.xxx.sales.saicorder.outerapp.tmall.enums.BusinessStatusEnum;
import com.xxx.sales.saicorder.outerapp.tmall.enums.MessageDealWithResultEnum;

/**
* 天猫visitor
*
* @author Euler
*/
public interface TmallVisitorStatus {

    /**
   * 判断数据库记录是否处理成功
   *
   * @param statusEnum
   *
   * @return
   */
    default boolean dbRecordIsFail(BusinessStatusEnum statusEnum) {
      return BusinessStatusEnum.ABNORMAL.equals(statusEnum) || BusinessStatusEnum.CREATE_ORDER_ABNORMAL.equals(statusEnum);
    }


    /**
   * 访问Db 已支付状态
   *
   * @param dbPayedStatus
   *
   * @return
   */
    MessageDealWithResultEnum visitDbStatus(DbPayedStatus dbPayedStatus);


    /**
   * 访问Db已核销状态
   *
   * @param dbChargeOffStatus
   *
   * @return
   */
    MessageDealWithResultEnum visitDbStatus(DbChargeOffStatus dbChargeOffStatus);


    /**
   * 访问Db 已退款状态
   *
   * @param dbCloseStatus
   *
   * @return
   */
    MessageDealWithResultEnum visitDbStatus(DbCloseStatus dbCloseStatus);


}TmallVisitorPayedStatuspackage com.xxx.sales.saicorder.outerapp.tmall.message.visitor;

import com.xxx.sales.saicorder.outerapp.tmall.enums.BusinessStatusEnum;
import com.xxx.sales.saicorder.outerapp.tmall.enums.MessageDealWithResultEnum;

/**
* 天猫已支付状态
* @author Euler
* @date 2022 2022/11/22
*/
public class TmallVisitorPayedStatus implements TmallVisitorStatus {
    /**
   * 访问Db 已支付状态
   *
   * @param dbPayedStatus
   *
   * @return
   */
    @Override
    public MessageDealWithResultEnum visitDbStatus(DbPayedStatus dbPayedStatus) {
      BusinessStatusEnum businessStatus = dbPayedStatus.getBusinessStatus();
      // 支付处理失败重试
      if (dbRecordIsFail(businessStatus)) {
            return MessageDealWithResultEnum.NORMAL;

      // 支付处理成功,又来支付成功消息,视为重复消息,清除
      }else{
            return MessageDealWithResultEnum.IS_REPEATED_MESSAGE;
      }
    }

    /**
   * 访问Db已核销状态
   *
   * @param dbChargeOffStatus
   *
   * @return
   */
    @Override
    public MessageDealWithResultEnum visitDbStatus(DbChargeOffStatus dbChargeOffStatus) {
      // 状态已经走到核销,又来已支付的消息。视为延时重复消息,清除
      return MessageDealWithResultEnum.IS_REPEATED_MESSAGE;
    }

    /**
   * 访问Db 已退款状态
   *
   * @param dbCloseStatus
   *
   * @return
   */
    @Override
    public MessageDealWithResultEnum visitDbStatus(DbCloseStatus dbCloseStatus) {
      // 状态已走到关闭,又来已支付消息,视为延时消息,清除
      return MessageDealWithResultEnum.IS_REPEATED_MESSAGE;
    }
}TmallVisitorCloseStatuspackage com.xxx.sales.saicorder.outerapp.tmall.message.visitor;

import com.xxx.sales.saicorder.outerapp.tmall.enums.MessageDealWithResultEnum;

/**
*
* 天猫已退款状态
* @author Euler
*/
public class TmallVisitorCloseStatus implements TmallVisitorStatus{
    /**
   * 访问Db 已支付状态
   *
   * @param dbPayedStatus
   *
   * @return
   */
    @Override
    public MessageDealWithResultEnum visitDbStatus(DbPayedStatus dbPayedStatus) {
      boolean dbRecordIsFail = dbRecordIsFail(dbPayedStatus.getBusinessStatus());
      // 已支付消息处理失败,订单没有创建成功,不能处理退款的消息
      if (dbRecordIsFail) {
            return MessageDealWithResultEnum.NO_SEQUENCE_MESSAGE;

      // 已支付消息处理成功,可以正常处理退款消息
      }else{
            return MessageDealWithResultEnum.NORMAL;
      }
    }

    /**
   * 访问Db已核销状态
   *
   * @param dbChargeOffStatus
   *
   * @return
   */
    @Override
    public MessageDealWithResultEnum visitDbStatus(DbChargeOffStatus dbChargeOffStatus) {
      // 已核销和已退款是互斥消息,处理了核销,就不能处理退款。(天猫核销后不能在天猫退款)
      return MessageDealWithResultEnum.IS_REPEATED_MESSAGE;
    }

    /**
   * 访问Db 已退款状态
   *
   * @param dbCloseStatus
   *
   * @return
   */
    @Override
    public MessageDealWithResultEnum visitDbStatus(DbCloseStatus dbCloseStatus) {
      boolean dbRecordIsFail = dbRecordIsFail(dbCloseStatus.getBusinessStatus());
      // 退款消息处理失败,再来退款重试消息,正常处理
      if (dbRecordIsFail) {
            return MessageDealWithResultEnum.NORMAL;

      // 退款消息处理成功了,再来退款消息,视为延时重复消息,清除
      }else {
            return MessageDealWithResultEnum.IS_REPEATED_MESSAGE;
      }
    }
}TmallVisitorChargeOffVisitorStatuspackage com.xxx.sales.saicorder.outerapp.tmall.message.visitor;

import com.xxx.sales.saicorder.outerapp.tmall.enums.MessageDealWithResultEnum;

/**
* 天猫核销完成状态
* @author Euler
*/
public class TmallVisitorChargeOffVisitorStatus implements TmallVisitorStatus {
    /**
   * 访问Db 已支付状态
   *
   * @param dbPayedStatus
   *
   * @return
   */
    @Override
    public MessageDealWithResultEnum visitDbStatus(DbPayedStatus dbPayedStatus) {
      boolean dbRecordIsFail = dbRecordIsFail(dbPayedStatus.getBusinessStatus());
      // 已支付消息处理失败,订单没有创建成功,不能处理核销的消息。消息重回队列
      if (dbRecordIsFail) {
            return MessageDealWithResultEnum.NO_SEQUENCE_MESSAGE;

      // 已支付处理成功,正常处理核销消息
      }else{
            return MessageDealWithResultEnum.NORMAL;
      }
    }

    /**
   * 访问Db已核销状态
   *
   * @param dbChargeOffStatus
   *
   * @return
   */
    @Override
    public MessageDealWithResultEnum visitDbStatus(DbChargeOffStatus dbChargeOffStatus) {
      boolean dbRecordIsFail = dbRecordIsFail(dbChargeOffStatus.getBusinessStatus());
      // 核销处理失败,又来核销重试消息,正常处理
      if (dbRecordIsFail) {
            return MessageDealWithResultEnum.NORMAL;

      // 核销处理成功,又来核销消息,视为重复消息,清除
      }else{
            return MessageDealWithResultEnum.IS_REPEATED_MESSAGE;
      }
    }

    /**
   * 访问Db 已退款状态
   *
   * @param dbCloseStatus
   *
   * @return
   */
    @Override
    public MessageDealWithResultEnum visitDbStatus(DbCloseStatus dbCloseStatus) {
      // 关闭后不在接收核销消息,清除
      return MessageDealWithResultEnum.IS_REPEATED_MESSAGE;
    }
}复杂的状态对应关系就如许解决了。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 项目中的《访问者模式》