【设计模式】用Java实现状态模式

2023-11-17

一.状态模式介绍与使用场景

状态模式是一种行为设计模式,它允许对象在内部状态发生改变时改变其行为。该模式将对象的行为包装在不同的状态类中,使得对象的行为可以根据其当前状态动态改变。

状态模式通常由以下几个角色组成:

  • 环境类(Context):环境类是拥有状态的对象,它将会根据当前状态来执行相应的行为。它维护了一个对抽象状态类的引用,用于切换和委托不同的状态处理。

  • 抽象状态类(State):抽象状态类定义了一个接口,用于具体状态类的实现。在该接口中声明了具体状态类需要实现的方法。

  • 具体状态类(Concrete State):具体状态类实现了抽象状态类的接口,并负责定义该状态下的具体行为。它包含了对环境类的引用,可以根据需要切换环境类的状态。

状态模式的核心思想是通过将对象的行为包装在不同的状态类中,使得对象可以根据其当前状态来改变行为,而不需要使用大量的条件判断语句。

状态模式适用场景:

  • 当一个对象的行为取决于其内部状态,并且需要在运行时根据状态改变行为时,状态模式非常有用。它允许对象在不同状态下执行不同的操作,而不需要使用复杂的条件判断语句。

  • 当对象具有大量的状态以及与每个状态相关的行为时,状态模式可以提供一种结构化的方式来管理和组织这些状态和行为。每个状态都可以表示为一个独立的状态类,使得代码更加清晰、可读性更高。

  • 当需要向对象的状态变化进行动态扩展时,状态模式提供了一种灵活的解决方案。通过添加新的状态类,并相应地调整环境类与状态类之间的关联,可以轻松地增加新的状态和行为。

  • 当多个对象需要共享同一组状态时,状态模式可以减少重复代码的编写。通过将状态封装在独立的状态类中,多个对象可以共享相同的状态实例,从而节省内存和代码维护成本。

总结起来,状态模式适用于以下情况:

  • 对象的行为取决于其内部状态,并且需要在运行时根据状态改变行为。
  • 对象具有多个状态以及与每个状态相关的行为。
  • 需要动态扩展对象的状态和行为。
  • 多个对象需要共享同一组状态。

通过使用状态模式,可以将复杂的条件判断逻辑转化为一组独立的状态类,提高代码的可读性、可维护性和可扩展性。同时,状态模式也能够帮助我们将对象的状态与行为进行解耦,使得代码更加灵活和可复用。

二.状态模式实现

 下面用一个简单的demo描述一下状态模式:

// 环境类 - 订单
class Order {
    private OrderState state;

    public Order() {
        state = new NewState();
    }

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

    public void process() {
        state.processOrder(this);
    }
}

// 抽象状态类
interface OrderState {
    void processOrder(Order order);
}

// 具体状态类 - 新订单
class NewState implements OrderState {
    public void processOrder(Order order) {
        System.out.println("Processing new order");
        // 在新订单状态下的处理逻辑
        // ...
        order.setState(new ShippedState()); // 切换状态
    }
}

// 具体状态类 - 已发货订单
class ShippedState implements OrderState {
    public void processOrder(Order order) {
        System.out.println("Processing shipped order");
        // 在已发货订单状态下的处理逻辑
        // ...
        order.setState(new DeliveredState()); // 切换状态
    }
}

// 具体状态类 - 已交付订单
class DeliveredState implements OrderState {
    public void processOrder(Order order) {
        System.out.println("Processing delivered order");
        // 在已交付订单状态下的处理逻辑
        // ...
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Order order = new Order();

        order.process(); // 处理新订单
        order.process(); // 处理已发货订单
        order.process(); // 处理已交付订单
    }
}

我们模拟了一个订单的状态变化过程。订单类 Order 是拥有状态的对象,它将根据当前状态来执行相应的行为。

抽象状态类 OrderState 定义了一个接口 processOrder(),具体状态类 NewStateShippedState DeliveredState 实现了该接口,并分别负责定义相应状态下的具体行为。

Main 类的 main 方法中,我们创建了一个订单对象,并连续调用了 process() 方法来处理订单。初始状态为新订单状态,调用 process() 方法后会切换到已发货订单状态,再次调用 process() 方法后会切换到已交付订单状态。

通过使用状态模式,订单对象能够根据不同的状态来改变其行为,避免了大量的条件判断语句,并使得代码更加可扩展和易维护。

以上只是一个简单的实现demo,实际开发中,还有很多场景适用于状态模式,例如电商订单的状态流转,下面我们写一个实现电商订单状态流转的状态模式例子:

// 环境类 - 订单
class Order {
    private OrderState state;

    public Order() {
        state = new NewState();
    }

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

    public void process() {
        state.processOrder(this);
    }
    
    public void cancel() {
        state.cancelOrder(this);
    }
}

// 抽象状态类
interface OrderState {
    void processOrder(Order order);
    void cancelOrder(Order order);
}

// 具体状态类 - 新订单
class NewState implements OrderState {
    public void processOrder(Order order) {
        System.out.println("Processing new order");
        // 在新订单状态下的处理逻辑
        // ...
        order.setState(new ShippedState()); // 切换状态
    }

    public void cancelOrder(Order order) {
        System.out.println("Cancelling new order");
        // 在新订单状态下的取消逻辑
        // ...
        order.setState(new CancelledState()); // 切换状态
    }
}

// 具体状态类 - 已发货订单
class ShippedState implements OrderState {
    public void processOrder(Order order) {
        System.out.println("Processing shipped order");
        // 在已发货订单状态下的处理逻辑
        // ...
        order.setState(new DeliveredState()); // 切换状态
    }

    public void cancelOrder(Order order) {
        System.out.println("Cancelling shipped order");
        // 在已发货订单状态下的取消逻辑
        // ...
        order.setState(new CancelledState()); // 切换状态
    }
}

// 具体状态类 - 已交付订单
class DeliveredState implements OrderState {
    public void processOrder(Order order) {
        System.out.println("Processing delivered order");
        // 在已交付订单状态下的处理逻辑
        // ...
    }

    public void cancelOrder(Order order) {
        System.out.println("Cancelling delivered order");
        // 在已交付订单状态下的取消逻辑
        // ...
        order.setState(new CancelledState()); // 切换状态
    }
}

// 具体状态类 - 取消订单
class CancelledState implements OrderState {
    public void processOrder(Order order) {
        System.out.println("Cannot process cancelled order");
        // 取消订单状态下不执行任何处理逻辑
    }

    public void cancelOrder(Order order) {
        System.out.println("Cannot cancel already cancelled order");
        // 取消订单状态下不执行任何取消逻辑
    }
}

// 使用示例
public class Main {
    public static void main(String[] args) {
        Order order = new Order();

        order.process(); // 处理新订单
        order.process(); // 处理已发货订单
        order.cancel(); // 取消已发货订单
        order.process(); // 处理已交付订单
    }
}

上述示例中,我们模拟了一个电商系统中的订单状态变化过程。订单类 Order 是拥有状态的对象,它根据当前状态来执行相应的操作。

抽象状态类 OrderState 定义了两个方法 processOrder() cancelOrder(),具体状态类 NewStateShippedStateDeliveredState CancelledState 实现了该接口,并分别负责定义相应状态下的具体行为。

Main 类的 main 方法中,我们创建了一个订单对象,并通过连续调用 process() 方法和 cancel() 方法来模拟订单状态的变化。初始状态为新订单状态,调用 process() 方法后会切换到已发货订单状态,再次调用 cancel() 方法后会切换到取消订单状态,最后再次调用 process() 方法会输出无法处理已取消订单的提示信息。

通过使用状态模式,订单对象能够根据不同的状态来改变其行为,避免了大量的条件判断语句,并使得代码更加可扩展和易维护。状态模式也能够帮助我们将对象的状态与行为进行解耦,使得代码更加灵活和可复用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【设计模式】用Java实现状态模式 的相关文章

随机推荐

  • (三) 区块链数据结构 – 交易

    区块由交易组成 区块体中包含若干项交易数据 交易 交易主要包含两类数据 交易输入和交易输出 交易输入用来指明钱的来源 交易输出用来指明钱的去向 除了交易输入和交易输出外 交易中还包含版本号和锁定时间 交易数据的存储结构如下 交易对象中的各个
  • Flink State 和 Fault Tolerance详解

    有状态操作或者操作算子在处理DataStream的元素或者事件的时候需要存储计算的中间状态 这就使得状态在整个Flink的精细化计算中有着非常重要的地位 记录数据从某一个过去时间点到当前时间的状态信息 以每分钟 小时 天汇总事件时 状态将保
  • 平面离散点集Delaunay三角化

    文章目录 定义 准则 特性 算法 1 逐点插入法 2 分治算法 3 生长算法 对比 参考 定义 在数学和计算几何中 三角化就是对于给定的平面中的离散点集P 生成三角形集合T的过程 一般来说给定一个点集 往往存在不止一个三角剖分 其中基于 D
  • 大数据时代下对NoSQL数据库的理解

    Web 2 0时代的到来 关系数据库越来越不能满足互联网应用的需求 导致了NoSQL的兴起 NoSQL数据库在大数据领域里越来越受欢迎 数据的高并发读写 数据的高可用性 海量数据存储 海量数据的实时分析 文档型数据库 代表 MongoDB
  • 边缘计算在物联网领域的研究与分析

    本文首发于 5G工业互联 作者黄泽龙 摘 要 物联网的发展开启了万物互联时代 设备的爆炸式增长和应用的多样化带来了海量数据 对传输带宽 时效性 异构接入等提出了新要求 边缘计算在靠近数据源侧进行数据处理 有效地减少数据传输量 降低服务响应时
  • c++虚函数实现机制及内存模型

    前言 大家都应该知道C 的精髓是虚函数吧 虚函数带来的好处就是 可以定义一个基类的指针 其指向一个继承类 当通过基类的指针去调用函数时 可以在运行时决定该调用基类的函数还是继承类的函数 虚函数是实现多态 动态绑定 接口函数的基础 可以说 没
  • 深度强化学习系列: “奖励函数”的设计和设置(reward shaping)

    概述 前面已经讲了好几篇关于强化学习的概述 算法 DPG gt DDPG 也包括对环境OpenAI gym的安装 baseline算法的运行和填坑 虽然讲了这么多 算法也能够正常运行还取得不错的效果 但是一直以来忽略了一个非常重要的话题 那
  • 篇六:线性查找

    线性查找 又称顺序查找 是一种最简单的查找方法 它的基本思想是从第一个记录开始 逐个比较记录的关键字 直到和给定的K值相等 则查找成功 若比较结果与文件中n个记录的关键字都不等 则查找失败 假设一个数组arr 23 98 56 76 38
  • 检验链表是否形成环

    以下两个方法只要是存在环快慢指针就一定相遇 1 快慢指针 2 fast先走K步 从第K个节点出发 gt gt 相当于在求倒数第K个节点 除了快慢指针 可以用记录步数是否相同 来判断是否会相遇 int has loop node t head
  • A failure occurred while executing org.jetbrains.kotlin.gradle.internal.KaptExecution

    今天在编译Kotlin项目时 遇到以下错误信息 信息中没有具体指明错误原因 只是报错 A failure occurred while executing org jetbrains kotlin gradle internal KaptE
  • IP首部报文字段

    一 IP首部报文字段 字段如下图所示 二 每个字段的含义 版本 表示 IP 协议的版本 通信双方使用的 IP 协议版本必须一致 目前广泛使用的IP协议版本号为 4 即 IPv4 首部长度 这个字段所表示数的单位是 32 位字长 1 个 32
  • postgreSQL中无法更改数据的问题

    增对这个bug 参考博客 解决Navicat修改Mysql数据后刷新恢复原样的问题 无法提交事务 Studiouss的博客 CSDN博客 发现我的问题是解决了 因为我确实没有设置主键 或者是设置主键没有保存造成的 这样就解决了 点击刷新 表
  • 自动化测试面试题及答案大全(2)

    问题1 Selenium是什么 流行的版本有哪些 是一个开源的web自动化测试的框架 支持多种编程语言 支持跨浏览器平台进行测试 Selenium 1 0或Selenium RC Selenium 2 0或Selenium Webdrive
  • VisualStudio神级插件——JetBrains Resharper 2018.2.3 Ultimate完美破解版教程

    VisualStudio神级插件 JetBrains Resharper 2018 2 3 Ultimate完美破解版 教程 ReSharper是一个JetBrains公司出品的著名的代码生成工具 是Visual Studio里面的一个插件
  • 中职本科计算机大学课程设置,中职学校计算机专业课程设置问题与对策研究——以湖南省五所中职学校为例...

    摘要 随着我国市场经济的发展 产业结构和劳动力结构不断调整 因此对劳动者的素质和结构都提出了新的要求 形成了对技能型人才需求的调整增长态势 技能型人才的紧缺 结构性失业问题已成为制约我国经济增长的瓶颈 中职教育作为目前职业教育的主体 它承担
  • 文件服务器 安全,文件服务器 安全

    文件服务器 安全 内容精选 换一换 云堡垒机支持批量导出资源信息 用于本地备份资源配置 以及便于快速管理资源基本信息 为加强资源信息安全管理 支持加密导出资源信息 导出的主机资源文件中包含主机基本信息 主机下所有资源账户信息 主机资源账户明
  • linuxmake没有指明目标并且找不到makefile_Makefile笔记

    一般来说 无论是C C 还是pas 首先要把源文件编译成中间代码文件 在Windows下也就是 obj 文件 UNIX下是 o 文件 即 Object File 这个动作叫做编译 compile 然后再把大量的Object File合成执行
  • ssh 连接报错:Unable to negotiate with 192.168.xx.xx port 22: no matching key exchange method found.

    用 ssh 连接 Linux 服务器时 很偶然的情况下出现了如下报错 Unable to negotiate with xx xx xx xx port 22 no matching key exchange method found Th
  • LeetCode题目笔记--12.整数转罗马数字

    题目描述 题目跟前面13题描述一样 就是问题变为整数转成罗马数字 思路 上一道题罗马数字转整数比较简单 因为不存在罗马数字表示冲突的问题 即不存在一个罗马数字对应多个整数 而这个问题中 就要考虑一下这个问题了 因为如果不加以约束的话 一个整
  • 【设计模式】用Java实现状态模式

    一 状态模式介绍与使用场景 状态模式是一种行为设计模式 它允许对象在内部状态发生改变时改变其行为 该模式将对象的行为包装在不同的状态类中 使得对象的行为可以根据其当前状态动态改变 状态模式通常由以下几个角色组成 环境类 Context 环境