深究设计模式之-状态模式

状态模式(State Pattern)是一种行为型设计模式,其主要目的是允许一个对象在其内部状态改变时改变其行为,看起来就像是改变了对象的类。状态模式将对象的状态封装成独立的类,使得对象状态的变化可以独立于对象本身的变化。

状态模式的重点是在其内部可以自动切换到需要的状态对象,新的状态对象拥有新的行为,比如一个自动售货机,它可以处于三种状态:正常运行缺货维护中。在正常运行状态下,它可以接受货币并提供商品;在缺货状态下,它不接受货币并显示"抱歉,商品已售罄";在维护中状态下,它完全关闭,不接受货币也不提供商品。
这里,自动售货机的行为取决于它的状态。状态模式允许售货机在不同的状态下有不同的行为,而且状态可以在运行时动态改变,比如当库存耗尽时,自动售货机的状态会从正常运行变为缺货状态。这样,状态模式使得系统能够更加灵活地应对不同的情况,同时也使得代码更加清晰易懂。

主要角色:

  1. 上下文(Context): 定义了客户端感兴趣的接口,并且维护一个具体状态的实例,可以根据当前状态调用不同的具体状态。

  2. 状态(State): 定义了一个接口,封装了与上下文的一个特定状态相关的行为。

  3. 具体状态(Concrete State): 实现了状态接口,包含了与特定状态相关的行为。

示例:

下面是一个简单的 Java 代码示例,实现了自动售货机的状态模式:

java 复制代码
package com.luke.designpatterns.statePattern;

// 状态接口
interface VendingMachineState {
    void pay();
    void getProduct();
}

// 具体状态类 - 正常运行状态
class NormalState implements VendingMachineState {
    @Override
    public void pay() {
        System.out.println("扫码购买产品!");
    }

    @Override
    public void getProduct() {
        System.out.println("购买成功!");
    }
}

// 具体状态类 - 缺货状态
class SoldOutState implements VendingMachineState {
    @Override
    public void pay() {
        System.out.println("抱歉,商品已售罄,扫码失败");
    }

    @Override
    public void getProduct() {
        System.out.println("抱歉,商品已售罄");
    }
}

// 具体状态类 - 维护中状态
class MaintenanceState implements VendingMachineState {
    @Override
    public void pay() {
        System.out.println("机器正在维护,无法扫码支付");
    }

    @Override
    public void getProduct() {
        System.out.println("机器正在维护");
    }
}

// 环境类 - 自动售货机
class VendingMachine {
    private VendingMachineState currentState;

    public VendingMachine() {
        // 初始状态为正常运行状态
        currentState = new NormalState();
    }

    public void setState(VendingMachineState newState) {
        this.currentState = newState;
    }

    public void insertCoin() {
        currentState.pay();
    }

    public void dispenseItem() {
        currentState.getProduct();
    }
}

// 客户端代码
public class StatePatternExample {
    public static void main(String[] args) {
        VendingMachine vendingMachine = new VendingMachine();

        vendingMachine.insertCoin();
        vendingMachine.dispenseItem();

        // 模拟缺货情况
        vendingMachine.setState(new SoldOutState());
        vendingMachine.insertCoin();
        vendingMachine.dispenseItem();

        // 模拟维护中情况
        vendingMachine.setState(new MaintenanceState());
        vendingMachine.insertCoin();
        vendingMachine.dispenseItem();
    }
}

在这个例子中,VendingMachine 类是环境类,负责维护当前的状态,并根据当前状态调用相应的方法。不同的状态由实现了 VendingMachineState 接口的具体状态类来表示,每个具体状态类实现了在特定状态下的行为。客户端代码可以通过调用 insertCoindispenseItem 方法与自动售货机进行交互。通过改变状态,自动售货机在不同的情况下表现出不同的行为。

适用场景

状态模式适用于以下场景:

  1. 对象的行为依赖于其状态,并且可以在运行时根据状态改变而改变行为。

    • 例如,一个文档编辑器,它可以处于编辑模式、预览模式和保存模式。不同模式下,工具栏和菜单的行为会有所不同。
  2. 对象有大量的条件语句来管理多个状态,并且这些条件语句使得代码难以维护和扩展。

    • 如果在代码中存在很多类似的if-else语句来处理对象的不同状态,状态模式可以帮助将这些状态的处理逻辑分散到不同的状态类中,使代码更清晰、可读性更好。
  3. 一个对象的状态转换在运行时可以发生,并且需要封装状态的变化。

    • 例如,在一个工作流应用中,一个任务可能有多个状态(待处理、处理中、已完成等),任务的状态可以在运行时发生变化,状态模式可以用来管理这些变化。
  4. 有些状态共享相同的行为,但在不同的状态下可能需要进行不同的处理。

    • 如果有几个状态在执行相同的操作时有共通的行为,但在细节上有所不同,状态模式可以减少重复代码,通过在每个状态类中实现相应的细节,使得代码更加模块化。
  5. 状态模式可以用于消除大量的条件性语句,提高代码的可维护性和可读性。

    • 当一个对象有多个状态,而这些状态在其行为上有明显的不同,使用状态模式可以将状态之间的转换和处理逻辑封装在独立的类中,使得代码更易于理解和维护。
相关推荐
一丝晨光3 分钟前
Java、PHP、ASP、JSP、Kotlin、.NET、Go
java·kotlin·go·php·.net·jsp·asp
罗曼蒂克在消亡7 分钟前
2.3MyBatis——插件机制
java·mybatis·源码学习
_GR18 分钟前
每日OJ题_牛客_牛牛冲钻五_模拟_C++_Java
java·数据结构·c++·算法·动态规划
coderWangbuer28 分钟前
基于springboot的高校招生系统(含源码+sql+视频导入教程+文档+PPT)
spring boot·后端·sql
无限大.31 分钟前
c语言200例 067
java·c语言·开发语言
余炜yw33 分钟前
【Java序列化器】Java 中常用序列化器的探索与实践
java·开发语言
攸攸太上33 分钟前
JMeter学习
java·后端·学习·jmeter·微服务
Kenny.志36 分钟前
2、Spring Boot 3.x 集成 Feign
java·spring boot·后端
不修×蝙蝠38 分钟前
八大排序--01冒泡排序
java
sky丶Mamba1 小时前
Spring Boot中获取application.yml中属性的几种方式
java·spring boot·后端