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

状态模式(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. 状态模式可以用于消除大量的条件性语句,提高代码的可维护性和可读性。

    • 当一个对象有多个状态,而这些状态在其行为上有明显的不同,使用状态模式可以将状态之间的转换和处理逻辑封装在独立的类中,使得代码更易于理解和维护。
相关推荐
Ama_tor3 分钟前
Flask |零基础进阶(上)
后端·python·flask
pyniu18 分钟前
Elasticsearch学习
后端·学习·elasticsearch·搜索引擎
再难也得平24 分钟前
[LeetCode刷题]283.移动零(通俗易懂的java题解)
java·算法·leetcode
野犬寒鸦33 分钟前
Java8 ConcurrentHashMap 深度解析(底层数据结构详解及方法执行流程)
java·开发语言·数据库·后端·学习·算法·哈希算法
百锦再37 分钟前
Java IO详解:File、FileInputStream与FileOutputStream
java·开发语言·jvm·spring boot·spring cloud·kafka·maven
郝学胜-神的一滴37 分钟前
在Vibe Coding时代,学习设计模式与软件架构
人工智能·学习·设计模式·架构·软件工程
追随者永远是胜利者43 分钟前
(LeetCode-Hot100)647. 回文子串
java·算法·leetcode·职场和发展·go
春和景明3601 小时前
mysql复习
java
九狼1 小时前
Flutter SSE 流式响用 Dio 实现 OpenAI 兼容接口的逐 Token 输出
http·设计模式·api
山岚的运维笔记1 小时前
SQL Server笔记 -- 第69章:时态表
数据库·笔记·后端·sql·microsoft·sqlserver