设计模式之状态模式

在日常开发中,我们经常会遇到这样的场景:一个对象在不同时刻有不同的状态,不同状态下它的行为也会发生变化。此时,使用大量if...else或switch语句会让代码变得混乱而难以维护。为了更优雅地应对这种问题,状态模式(State Pattern)应运而生。

1. 概念

状态模式是行为型模式之一。它允许一个对象在其内部状态发生变化,改变它的行为,看起来就像修改了它的类一样。

简单来说:对象的行为取决于它的状态,并且可以在运行时根据状态改变行为。

状态模式主要包含以下角色:

**环境类(Context):**也称为上下文,它定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换。

**抽象状态类(State):**定义一个接口,用以封装环境对象中的特定状态所对应的行为,可以有一个或多个行为。

**具体状态类(Concrete State):**实现抽象状态所对应的行为,并且在需要的情况下进行状态切换。

2. 代码实现

这里我们以一个简单的订单状态来举例,我们一个订单可能拥有很多状态,比如代付款、待发货、已发货、已完成等状态,这里我们就来模拟一下一个订单完成的全状态。

我们首先定义抽象状态,以及其相关实现:

java 复制代码
public interface OrderState {
    void handle();
}
java 复制代码
public class PendingPaymentState implements OrderState {
    public void handle() {
        System.out.println("订单待付款,提示用户付款...");
    }
}

public class PaidState implements OrderState {
    public void handle() {
        System.out.println("订单已付款,准备发货...");
    }
}

public class ShippedState implements OrderState {
    public void handle() {
        System.out.println("订单已发货,等待确认收货...");
    }
}

public class CompletedState implements OrderState {
    public void handle() {
        System.out.println("订单已完成,谢谢惠顾!");
    }
}

其次我们定义一个环境类:

java 复制代码
public class OrderContext {
    private OrderState state;

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

    public void request() {
        if (state == null) {
            throw new IllegalStateException("订单状态未设置!");
        }
        state.handle();
    }
}

最后我们定义一个测试类:

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

        order.setState(new PendingPaymentState());
        order.request(); // 输出:订单待付款,提示用户付款...

        order.setState(new PaidState());
        order.request(); // 输出:订单已付款,准备发货...

        order.setState(new ShippedState());
        order.request(); // 输出:订单已发货,等待确认收货...

        order.setState(new CompletedState());
        order.request(); // 输出:订单已完成,谢谢惠顾!
    }
}

其实经验丰富的程序员可以联想到一个词:那就是状态机,我们也可以对上述的案例进行进一步的加强,比如可以让每一个状态都拥有切换状态的行为,这样环境类可以直接形成一个状态流程,可以通过调用该状态的方法就可以实现与其他状态的关联。

3. 应用场景

  • 流程框架
  • 状态机
  • ......

4. 总结

使用状态模式可以让我们的业务逻辑更加的清晰,并且具有更高的扩展性,同时符合开闭原则,可以让我们业务代码避免过于臃肿。但是缺点在于会增加我们类的数量,我们业务每次增加一个状态就会添加一个新的状态实现类,但是其实比起if...else还是更加优雅的。

其实状态模式用好了对于我们开发人员来说是跟提高我们代码的可读性,比如目前我所工作的项目中就有应用到,我也深刻体会到了状态模式扩展性的作用有多高。

相关推荐
晚安code5 小时前
设计模式入门:吃透 SOLID 原则与迪米特法则,再学 5 个高频模式
后端·设计模式
染指11109 小时前
135.Agent-多Agent框架-LangChain多智能体(SubAgents子代理)
数据库·人工智能·设计模式·langchain·agent·agents
lank_M1 天前
抠图换深色背景有白边?先分清直通和预乘alpha
图像处理·人工智能·计算机视觉·状态模式
弹简特1 天前
【Java项目-企悦抽】17-抽奖模块02-抽奖接口实现
java·开发语言·状态模式·springboot
路弥行至1 天前
【Head First 设计模式】第 2 章:观察者模式 —— 用现代 C++ 重新解读“交互对象的松耦合
c++·经验分享·笔记·观察者模式·设计模式·入门教程·headfirst
YYYing.1 天前
【设计模式系列 (九) 】装饰器模式
c++·后端·设计模式·装饰器模式·c/c++
我是你的开心果7781 天前
ai全栈软件开发学习day27
人工智能·学习·状态模式
沫璃染墨1 天前
《从零入门Linux系统篇(五十六):线程篇·九——生产者消费者模型:从条件变量到BlockingQueue实现》
linux·服务器·c++·驱动开发·设计模式·架构·系统架构
弹简特2 天前
【Java项目-企悦抽】16-抽奖模块01-获取活动完整信息接口实现
java·开发语言·状态模式·springboot
c萱2 天前
AI产品经理——01基础认知篇
设计模式·prompt·aigc·产品经理·ai编程·gitcode·ai-native