首页 > 其他分享 >项目中的《访问者模式》

项目中的《访问者模式》

时间:2024-12-17 21:52:51浏览次数:3  
标签:return 项目 MessageDealWithResultEnum tmall 模式 saicorder com public 访问者

这个模式核心思想是将基本的数据对象和对应的操作相互分离。数据对象就只是数据对象,如果想要扩展操作,就扩展对应的visitor。

这种模式下的两次分派

第一次分派,是将对数据对象本身进行分派,可以有不同的实现。
第二次分派,是visitor接收不同的数据对象。
结果就是数据对象接受了visitor,然后visitor中组合了数据对象。

这个项目中的使用场景

对于订单状态,有两个数据载体,一个是数据库已存在的当前的状态,一个是消息推送过来的状态。通过两个载体的状态的组合,能做出响应的动作。
处理逻辑如下⬇︎⬇︎⬇︎
image

UML是这样的⬇︎⬇︎⬇︎
image

实际代码是这样的⬇︎⬇︎⬇︎

DbStatus
package 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);
    }
}

DbPayedStatus
package 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);
    }
}

DbCloseStatus
package 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);
    }
}

DbChargeOffStatus
package 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);
    }

}

TmallVisitorStatus
package 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);


}

TmallVisitorPayedStatus
package 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;
    }
}

TmallVisitorCloseStatus
package 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;
        }
    }
}

TmallVisitorChargeOffVisitorStatus
package 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;
    }
}

复杂的状态对应关系就这样解决了。

标签:return,项目,MessageDealWithResultEnum,tmall,模式,saicorder,com,public,访问者
From: https://www.cnblogs.com/euler-blog/p/18613488

相关文章

  • vite 创建react hook项目
    create-vite安装create-vite是一个用于快速搭建Vite项目的脚手架工具。你可以通过npm(Node包管理器)来安装它。通常情况下,你不需要单独安装create-vite,因为你可以直接使用npx(Node包运行器)来运行它。npx是npm5.2.0版本及以上版本自带的一个工具,用于执行在本地或远程注册......
  • 《装饰器模式》VS《代理模式》
    装饰器强调的是动态功能增强,而这种增强是比单继承更加的灵活的方式,可以动态的给基类扩展不同的功能。继承实现增强有不同结构如果是按照最小原则,是这样的⬇︎⬇︎⬇︎如果不想那么多类文件,是这样的⬇︎⬇︎⬇︎虽然这样都能实现让子类拥有base/A/B三个操作,但如果现在只需要base/B操作怎......
  • 「九」HarmonyOS 5 端云一体化实战项目——「M.U.」应用云侧开发云数据库
    1立意背景M.代表“我”,U.代表“你”,这是一款用于记录情侣从相识、相知、相恋、见家长、订婚直至结婚等各个阶段美好记忆留存的应用程序。它旨在为情侣们提供一个专属的空间,让他们能够将一路走来的点点滴滴,如初次相遇时的心动瞬间、逐渐了解彼此过程中的深入交流、甜蜜......
  • 不错的AI项目集合
    最近收集了一些不错的AI项目。AutoGPT:AutoGPT的愿景是让每个人都可以使用和构建无障碍AI。我们的使命是提供工具,以便您可以专注于重要的事情。StableDiffusionwebUI:图片生成工具,StableDiffusionwebUI。langchain:构建上下文感知推理应用程序,AI框架。AppFlowy:使用AI将......
  • 《单例模式》我只用这一种
    双重检查是我用的最多的一种。因为它是一种线程安全的写法,而这种写法可以应用到各种场景中。比如:涉及到多线程共享的数据,在更新时候的使用。比如这种:其他的方式也有,比如内部类的实现方式。点击查看代码publicclassSingletonEagerInnerClass{privateSingletonEage......
  • Redis篇之Redis高可用模式参数调优,提高Redis性能
    1.Redis高可用模式核心Redis高可用模式的核心是使用主从复制和自动故障转移机制来确保系统在某些节点发生故障时仍然可以正常工作。常用的高可用架构包括RedisSentinel模式和RedisCluster模式,其中Sentinel模式是为了提供高可用性而专门设计的解决方案。在RedisSent......
  • Maven项目在不同 JDK 版本下的兼容性问题及解决方案
    Maven项目在不同JDK版本下的兼容性问题及解决方案引言在日常开发中,Maven是Java项目构建和管理的核心工具。然而,随着JDK版本的不断更新,开发者可能会遇到一些兼容性问题。例如,某些Maven插件在特定JDK版本下无法正常工作,或者依赖下载失败。本文将通过一个实际案例,分析......
  • 都在使用的《模版模式》
    模版符合开闭原则,到处用于钩子方法。有的钩子方法不会改变行为,有的钩子会改变运行轨迹。框架中到处使用。Channel中定义了需要的操作,AbstractChannel实现了核心功能,然后不同的Channel实现只需要告知具体channel的描述信息即可。Channel接口⬇︎⬇︎⬇︎点击查看代码packagecom.x......
  • 项目解决方案:同城多地店铺通过监控云租用平台,实现对店铺视频资源的统一观看和管理
    目录一.需求确认1.1项目背景1.1.1行业背景与市场需求1.1.2现存问题和挑战1.2具体需求阐述1.2.1流畅观看视频需求1.2.2视频资源整合需求1.2.3权限管理需求1.2.4手机可看视频需求二.方案实现难点2.1账号集中管理2.2权限分配管理2.3多客户端同步观看三.建设目标总览......
  • 【YashanDB知识库】如何处理yasql输入交互模式下单行字符总量超过限制4000字节
    现象在yasql执行sql语句后报错:YASQL-00021inputlineoverflow(>4000byteatline4)原因yasql在交互模式模式下单行字符总量限制4000字节,超出该限制即报错。交互式模式下,yasql会显示一个提示符,通常是SQL>,等待用户输入命令,用户执行的每个命令都会立即执行,并显示结果。......