设计模式——状态模式

设计模式------状态模式

简单介绍

状态模式(State Pattern)是一种行为设计模式,它允许对象在其内部状态改变时改变其行为。状态模式的主要目的是将状态的转换逻辑和状态相关的操作封装在不同的类中,从而使得系统更易于扩展和维护

说白话就是在代码中合理的维护状态机的变更,这看上去很简单,不过也很重要,遇到适当的需求画出状态机变更图并且合理的实现它,是一个架构师的必经之路

主要组成部分:

1,Context(上下文):定义一个类,维护一个对当前所有涉及到的状态对象的引用,这东西很可能是聚合根

2,State(状态接口):定义一个接口,用于封装与状态相关的操作

3,ConcreteState(具体状态类):实现状态接口,每个具体状态类都包含与该状态相关的行为

一个例子

假设我们有一个简单的订单系统,订单有多种状态,如待支付、已支付、已发货等。每种状态下的订单行为不同

如果我们封装了下单、支付、发货接口,就会发现,订单类在待支付状态时,也是可以调用发货接口的,这显然不合理,用状态模式优化一下看看:

1,定义 Context 类

java 复制代码
public class Order {
    private OrderState orderState;

    public Order() {
        this.orderState = new PendingPaymentState(); // 默认状态为待支付
    }

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

    public void pay() {
        orderState.pay(this);
    }

    public void ship() {
        orderState.ship(this);
    }

    public void deliver() {
        orderState.deliver(this);
    }
}

2,定义 State 接口

java 复制代码
public interface OrderState {
    void pay(Order order);
    void ship(Order order);
    void deliver(Order order);
}

3,实现类

java 复制代码
public class PendingPaymentState implements OrderState {
    @Override
    public void pay(Order order) {
        System.out.println("Order is paid.");
        order.setState(new PaidState());
    }

    @Override
    public void ship(Order order) {
        System.out.println("Cannot ship an unpaid order.");
    }

    @Override
    public void deliver(Order order) {
        System.out.println("Cannot deliver an unpaid order.");
    }

    @Override
    public String toString() {
        return "Pending Payment";
    }
}

public class PaidState implements OrderState {
    @Override
    public void pay(Order order) {
        System.out.println("Order is already paid.");
    }

    @Override
    public void ship(Order order) {
        System.out.println("Order is shipped.");
        order.setState(new ShippedState());
    }

    @Override
    public void deliver(Order order) {
        System.out.println("Cannot deliver an unshipped order.");
    }

    @Override
    public String toString() {
        return "Paid";
    }
}

public class ShippedState implements OrderState {
    @Override
    public void pay(Order order) {
        System.out.println("Order is already paid and shipped.");
    }

    @Override
    public void ship(Order order) {
        System.out.println("Order is already shipped.");
    }

    @Override
    public void deliver(Order order) {
        System.out.println("Order is delivered.");
        order.setState(new DeliveredState());
    }

    @Override
    public String toString() {
        return "Shipped";
    }
}

public class DeliveredState implements OrderState {
    @Override
    public void pay(Order order) {
        System.out.println("Order is already delivered.");
    }

    @Override
    public void ship(Order order) {
        System.out.println("Order is already delivered.");
    }

    @Override
    public void deliver(Order order) {
        System.out.println("Order is already delivered.");
    }

    @Override
    public String toString() {
        return "Delivered";
    }
}

具体使用:

java 复制代码
public class StatePatternDemo {
    public static void main(String[] args) {
        Order order = new Order();

        System.out.println(order);
        order.pay();
        System.out.println(order);

        order.ship();
        System.out.println(order);

        order.deliver();
        System.out.println(order);
    }
}

一些思考

我接触的所有项目,目前没一个用过这个模式的,因为它的缺点很明显,多定义了很多状态类,而这些状态类的大多数方法都没什么用

不过它为我们的编程提供了一些合理的指导思想。比如我们很多时候会遇到类似这样的问题:一个大订单下面有很多小订单,我们在修改大文档状态的时候也需要修改该文档下评论状态、推荐文章的状态等,我们需要在业务中维持各个状态的一致性

借鉴状态模式,我们可以先将状态机变更的流程图画出来, 比如:

每一个状态变更操作抽象出一个方法,这些方法可以放在聚合根中,调用这些方法的时候统一变更这些状态,这样这些状态就变得易于维护了

相关推荐
_Evan_Yao2 小时前
Redis 缓存穿透、击穿、雪崩,一次讲清!
java·spring·mybatis
梓豪csd3 小时前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
秋饼3 小时前
Spring AI 2.1 Message Parts 深度实战:推理签名回放与跨轮记忆持久化的源码级落地
java·ai·技术分享·后端开发
thefool1122664 小时前
TCP 1
java·1024程序员节
金銀銅鐵6 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
AI人工智能+电脑小能手6 小时前
一次请求打几个下游,这个Java并行任务工具类6个方法按序聚合
java·线程池·并发编程·1024程序员节·批量处理·并行任务
paopaokaka_luck8 小时前
心理咨询管理系统(WebSocket实时沟通、基于用户的协同过滤、 ECharts多维分析、 预约业务流程、预约校验与定时处理)
java·vue.js·spring boot·mysql·spring·echarts·1024程序员节
2301_32241428048 小时前
springboot农产品交易平台的设计与实现08055-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·spring boot·redis·mysql·tomcat·maven·mybatis
考虑考虑9 小时前
JDK26的JEP 500属性
java·后端·java ee
LMT流氓兔9 小时前
第五单元——第十二课:把脚本整理成项目
java·数据库·python·langchain·1024程序员节