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

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

    • 当一个对象有多个状态,而这些状态在其行为上有明显的不同,使用状态模式可以将状态之间的转换和处理逻辑封装在独立的类中,使得代码更易于理解和维护。
相关推荐
界面开发小八哥16 分钟前
「Java EE开发指南」如何用MyEclipse创建一个WEB项目?(三)
java·ide·java-ee·myeclipse
ai小鬼头35 分钟前
Ollama+OpenWeb最新版0.42+0.3.35一键安装教程,轻松搞定AI模型部署
后端·架构·github
idolyXyz42 分钟前
[java: Cleaner]-一文述之
java
一碗谦谦粉1 小时前
Maven 依赖调解的两大原则
java·maven
萧曵 丶1 小时前
Rust 所有权系统:深入浅出指南
开发语言·后端·rust
netyeaxi1 小时前
Java:使用spring-boot + mybatis如何打印SQL日志?
java·spring·mybatis
收破烂的小熊猫~2 小时前
《Java修仙传:从凡胎到码帝》第四章:设计模式破万法
java·开发语言·设计模式
猴哥源码2 小时前
基于Java+SpringBoot的动物领养平台
java·spring boot
老任与码2 小时前
Spring AI Alibaba(1)——基本使用
java·人工智能·后端·springaialibaba
小兵张健2 小时前
武汉拿下 23k offer 经历
java·面试·ai编程