优雅地管理对象状态:深入剖析状态模式

阅读建议

嗨,伙计!刷到这篇文章咱们就是有缘人,在阅读这篇文章前我有一些建议:

  1. 本篇文章大概2000多字,阅读时间长可能需要2-3分钟;
  2. 设计模式属于程序的设计思想、方法类的内容,阅读一遍,在理解上不一定会很透彻,建议收藏起来,有空多看看,书读百遍,其义自现;
  3. 创作不易,免费的点赞、关注,请走上一走,也算是对博主一些鼓励,可以让我更有动力输出更多的干货内容;

什么是状态模式

状态模式是一种行为型设计模式,允许对象在内部状态发生改变时改变它的行为。它适用于行为随状态改变而改变的场景,如一个操作中含有庞大的多分支结构,并且这些分支取决于对象的状态。状态模式的核心是状态与行为绑定,不同的状态对应不同的行为。它定义了各种状态类,每个状态类中定义了对应的状态行为,并且状态类之间通过继承实现状态的转移。通过使用状态模式,可以将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足单一职责原则。

状态模式的核心原理

状态模式的核心原理是通过封装状态和行为,并使用上下文对象管理状态切换,实现对象在不同状态下具有不同行为的设计模式

状态模式的核心角色包括:

  1. 环境(Context)角色:也称为上下文,它定义了客户感兴趣的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
  2. 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。
  3. 具体状态(Concrete State)角色:实现抽象状态所对应的行为。

状态模式如何实现

需求描述

状态模式很简单,也很容易理解,这里我举一个生活中的小例子来说明一下:比如我,平时一般都是7点钟起床开始洗漱,8点钟开车出门,9点钟到达公司,开始进入作状态,这就是简单朴实的一天。类似这种不同的状态或时刻,会触发一些固定的动作,并且动作之间具有一定的连贯性,使用状态模式就是一个比较好的选择。如果使用状态模式来模拟一下起床去上班这个过程,应该怎么实现呢?

实现方法

1、TaskState.java:声明抽象的任务状态,即抽象状态角色,封装了特定时刻下的行为;

java 复制代码
/**
 * 任务状态抽象
 */
public abstract class TaskState {

    /**
     * 任务在某个状态时,做一些事
     */
    public abstract void doSomething(TaskContext taskContext);
}

2、TaskContext.java:任务的上下文环境,持有一个任务状态,并定义了当前任务状态一下具体动作;

java 复制代码
/**
 * 任务管理上下文
 */
public class TaskContext {
    private TaskState taskState;

    public TaskState getTaskState() {
        return taskState;
    }

    public void setTaskState(TaskState taskState) {
        this.taskState = taskState;
    }

    public void handle(){
        this.taskState.doSomething(this);
    }
}

3、SevenState.java、EightState.java、NineState.java:继承于抽象的任务状态,是具体状态,分别实现了7点钟、8点钟、9点钟时的特定动作;

java 复制代码
/**
 * 7点钟的任务
 */
public class SevenState extends TaskState{
    @Override
    public void doSomething(TaskContext taskContext) {
        System.out.println("7:00>起床洗漱");
        taskContext.setTaskState(new EightState());
    }
}
java 复制代码
/**
 * 8点状的任务
 */
public class EightState extends TaskState{
    @Override
    public void doSomething(TaskContext taskContext) {
        System.out.println("8:00>开车出门去上班");
        taskContext.setTaskState(new NineState());
    }
}
java 复制代码
/**
 * 9点钟的任务
 */
public class NineState extends TaskState{
    @Override
    public void doSomething(TaskContext taskContext) {
        System.out.println("9:00>到达公司,开始工作");
    }
}

4、Client.java:编写业务客户端把各任务状态整合到上下文环境中;

java 复制代码
public class Client {
    public static void main(String[] args) {
        SevenState sevenState = new SevenState();
        TaskContext taskContext = new TaskContext();
        taskContext.setTaskState(sevenState);
        taskContext.handle();
        taskContext.handle();
        taskContext.handle();
    }
}

状态模式适用哪些场景

状态模式适用于处理一个对象在其内部状态改变时,其行为也随之改变的场景。具体来说,状态模式适用于以下特征的业务场景:

  1. 一个对象存在多个状态,这些状态可以相互转换。
  2. 不同状态下,对象的行为不同。
  3. 状态转换过程比较复杂,将状态判断逻辑转移到代表不同状态的一系列类中可以简化代码。

例如,在视频播放的业务场景中,播放器有初始状态、播放状态、暂停状态、停止状态、快进状态等多种状态,将这些状态都封装到代表不同状态的类中,可以将复杂的判断逻辑简化,将这些逻辑扩展到不同的状态类中。

此外,状态模式还适用于电梯运行、购买物品等场景。在电梯运行场景中,电梯的运行状态包括停止、上行、下行等,不同状态下行为不同。在购买物品场景中,可以将购物车中的商品订单状态封装到代表不同状态的类中,如未付款、已付款、已取消等状态,简化判断逻辑并提高代码可读性和可维护性。

状态模式的优点和缺点

优点

  1. 状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足"单一职责原则"。
  2. 减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
  3. 有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。

缺点

  1. 状态模式的使用必然会增加系统的类与对象的个数。
  2. 状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。

总结

在实现上,状态模式增加了系统的类与对象的个数,并且状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。因此,在使用状态模式时需要注意其适用场景和优缺点,并根据实际情况进行权衡和选择。

相关推荐
结衣结衣.13 分钟前
LeetCode热题100(滑动窗口篇)
java·c++·python·算法·leetcode·职场和发展
鹿屿二向箔30 分钟前
搭建一个基于Spring Boot的书籍学习平台
spring boot·后端·学习
孑么41 分钟前
力扣 完全平方数
java·算法·leetcode·职场和发展·动态规划
2401_8979083141 分钟前
2019-Android-高级面试题总结-从java语言到AIDL使用与原理
android·java·开发语言
GISer_Jing1 小时前
React中用到的Javascript设计模式详解
javascript·react.js·设计模式
mikey棒棒棒1 小时前
RabbitMQ-消息可靠性以及延迟消息
java·开发语言·中间件·rabbitmq·消息可靠性·死信交换机·惰性队列
m0_748235611 小时前
【SpringBoot】【log】 自定义logback日志配置
java·spring boot·logback
MasterNeverDown1 小时前
RabbitMQ踩坑- RabbitMQ service is already present
开发语言·后端
m0_672449602 小时前
Java日志配置
java·开发语言·单元测试
*TQK*2 小时前
C++范围基 for 循环
java·开发语言