我所理解的设计模式系列·第16篇·电商系统基于状态模式实现订单支付业务「建议收藏」

我所理解的设计模式系列·第16篇·电商系统基于状态模式实现订单支付业务「建议收藏」今天要跟大家聊的是状态模式(State Pattern),它描述的是程序因为内部状态发生转变而有不同行为的情况。比如说自动售货机,当用户把钱塞入投币处,对于自动售货机来说,它的投币状态变成了已投币

「这是我参与2022首次更文挑战的第28天,活动详情查看:2022首次更文挑战

今天要跟大家聊的是状态模式(State Pattern),它描述的是程序因为内部状态发生转变而有不同行为的情况。比如说自动售货机,当用户把钱塞入投币处,对于自动售货机来说,它的投币状态变成了已投币,于是它的行为也发生了变化——将货物移动到取货处。完成后,自动售货机的投币状态又转移回了未投币,于是它的行为又发生了变化——不出货。

design-patttern-16-状态模式-封面

1. 定义

状态模式是一种行为型设计模式,它的定义是:“允许对象在其内部状态发生改变时改变其行为,这个对象看起来像改变了其类。

这里需要注意的是,对象会因为自身内部状态的变动而改变自身行为,这看起来跟策略模式有点像,只不过在策略模式中,客户端通过传入具体的策略类来执行不同的业务逻辑。而状态模式中,对象的状态不是维护在具体状态类中而是在上下文角色中的,同时在执行过程中上下文角色会调用具体状态类的状态转移方法改变对象的行为

2. 类图

在状态模式中,有这样几种角色:

  • 环境角色(Context):定义客户端需要的接口,并且负责具体状态的切换
  • 抽象状态角色(State):通常是接口或抽象类,负责对象状态定义,并且封装环境角色用以实现状态切换
  • 具体状态角色(ConcreteState):抽象状态角色的实现类,每个具体状态必须完成两个职责:当前状态需要做的事以及如何转移到其他状态

状态模式的类图如下:

design-patttern-16-状态模式-1-类图

3. 示例

今天就以电商系统中订单支付业务来聊一聊状态模式的应用。首先来说一下缩减后的简单业务:

  • 当用户选购商品后确认订单,订单状态变为待支付
  • 当用户支付成功后,订单状态变为待发货
  • 当商家发货后,订单状态变为待收货
  • 当用户收货后,订单状态变为已完成

当然在业务描述中没有涉及异常场景,这里就不做讨论了。

首先定义订单状态抽象类,它持有上下文角色(订单上下文)同时描述了该状态下订单的执行逻辑(包含订单状态转移逻辑),其代码如下:

public abstract class OrderState {

    private OrderContext context;

    // 订单在指定状态下,系统执行的业务
    public abstract void handle();
  
  	// 省略 setter/getter 方法
}

然后定义待支付、待发货、待收货这三个订单状态,其代码如下:

public class UnPaidState extends OrderState {

    @Override
    public void handle() {
        System.out.println("当前订单状态为[待支付]");
        System.out.println("用户支付成功");
        super.getContext().setState(new UnDeliverState());
        System.out.println("当前订单状态为[待发货]");
    }
}

public class UnDeliverState extends OrderState {

    @Override
    public void handle() {
        System.out.println("当前订单状态为[待发货]");
        System.out.println("商家发货成功");
        super.getContext().setState(new UnReceiveState());
        System.out.println("当前订单状态为[待收货]");
    }
}

public class UnReceiveState extends OrderState {

    @Override
    public void handle() {
        System.out.println("当前订单状态为[待收货]");
        System.out.println("用户确认收货");
        System.out.println("当前订单状态为[已完成]");
    }
}

然后定义订单上下文类,其代码如下:

public class OrderContext {

    private OrderState state;

    public void setState(OrderState state) {
        this.state = state;
        this.state.setContext(this);
    }

    public void handle() {
        // 执行该状态下的业务逻辑
        this.state.handle();
    }
}

然后编写测试代码:

public class Test {
    public static void main(String[] args) {
        OrderContext context = new OrderContext();
        context.setState(new UnPaidState());
        System.out.println("-----用户确认订单-----");
        context.handle();
        System.out.println("-----商家发货-----");
        context.handle();
        System.out.println("-----用户确认收货-----");
        context.handle();
    }
}

输出结果为:

-----用户确认订单-----
当前订单状态为[待支付]
用户支付成功
当前订单状态为[待发货]
-----商家发货-----
当前订单状态为[待发货]
商家发货成功
当前订单状态为[待收货]
-----用户确认收货-----
当前订单状态为[待收货]
用户确认收货
当前订单状态为[已完成]

4. 使用场景

状态模式的使用场景是:

  • 行为随状态改变而改变
  • 如果代码中存在大量条件、分支判断语句,可以考虑使用状态模式重构

5. 小结

本文讲述了状态模式,它的定义是——允许对象在其内部状态发生改变时改变其行为,这个对象看起来像改变了其类。

状态模式的优点是:

  • 避免程序的复杂性,提高系统的可维护性:能够避免大量条件、分支判断语句
  • 符合单一职责原则,扩展性、封装性很好
    • 每个状态都由一个具体状态类实现
    • 如果需要新增状态只需要新增具体状态类
    • 如果需要修改状态只需要修改对应的子类即可

状态模式的缺点是:

  • 如果状态非常多的话,可能导致存在大量具体状态类,影响代码可读性
  • 不符合开闭原则,状态转移逻辑是定义在具体状态类中的,若需要修改大量源码

6. 参考资料

最后,本文收录于个人语雀知识库: 我所理解的后端技术,欢迎来访。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/12892.html

(0)

相关推荐

  • Msql基础版_mysql好学吗

    Msql基础版_mysql好学吗 mysql简介 1、什么是数据库 ? 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据…

    2023-03-24
    148
  • [20191206]隐含参数_db_always_check_system_ts.txt「建议收藏」

    [20191206]隐含参数_db_always_check_system_ts.txt「建议收藏」[20191206]隐含参数_db_always_check_system_ts.txt–//今年年头我做tab$删除恢复时,遇到的问题,就是遇到延迟块清除的问题.参考链接:http://blog.

    2022-12-25
    134
  • MyCat教程五:实现分库分表[通俗易懂]

    MyCat教程五:实现分库分表[通俗易懂]  本文我们来介绍下MyCat的分库分表操作 分库分表 一、分片规则介绍   在rule.xml中定义了各种myCat支持的分片规则。 取模mod-long 自然月分片 sharding-by-mo…

    2022-12-16
    144
  • 简道云这个低代码开发平台怎么样,靠谱吗?

    简道云这个低代码开发平台怎么样,靠谱吗?拖拖拽拽做应用开发,就是低代码开发平台给大家最直接印象,也是低代码开发平台基本特征。这一点,现在很多低代码开发平台都能够做得到。根据相关机构调研

    2022-12-14
    207
  • spark-sql中视图关联表结果不匹配问题

    spark-sql中视图关联表结果不匹配问题在sparkSQL 中将计算结果保存为视图,关联其他表后出现结果匹配错误,通过分析发现,是因为sql语句中使用了表达式 row_number() over(order by 1) 其实该表达式并没有执

    2023-03-16
    154
  • 【JDBC】笔记(3)-「终于解决」

    【JDBC】笔记(3)-「终于解决」1.Statement 编译一次,只执行一次,PreparedStatement 编译一次,可执行n次,所以 PreparedStatement 效率较高……

    2023-05-03
    153
  • Python import报错

    Python import报错 Python是一种高级编程语言,拥有丰富的扩展库,方便编程人员快速开发自己的程序。import语句是Python语言中常用的一个命令,用于导入扩展模块或自定义模块。当Python程序中使用import语句出现错误时,就需要进行相关的调试和解决问题,避免影响程序的正常运行。

    2024-09-14
    29
  • Python正则表达式:字符串匹配和提取的利器

    Python正则表达式:字符串匹配和提取的利器Python作为一种强大的编程语言,它具有许多特性,正则表达式就是其中之一。这项技术可以被用来搜索、替换和提取字符串中的信息,并且可以分析各种文本数据。在本文中,我们将学习如何使用Python的正则表达式帮助我们提取和匹配文本数据。

    2024-04-10
    87

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注