状态模式——对象状态及其转换

这篇具有很好参考价值的文章主要介绍了状态模式——对象状态及其转换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、简介

1.1、概述

在软件系统中,有些对象也像水一样具有多种状态,这些状态在某些情况下能够相互转换,而且对象在不同的状态下也将具有不同的行为。为了更好地对这些具有多种状态的对象进行设计,可以使用一种被称为状态模式的设计模式。

状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式。状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化。对于客户端而言,无须关心对象状态的转换以及对象所处的当前状态,无论对于何种状态的对象,客户端都可以一致性地处理。

1.2、定义

状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。

2、解析

2.1、UML类图

在状态模式中引入了抽象状态类和具体状态类,它们是状态模式的核心,其结构如下图所示。
状态模式——对象状态及其转换,设计模式,状态模式
可以看出,在状态模式结构图中包含以下3个角色:

  1. Context(环境类):环境类又称为上下文类,它是拥有多种状态的对象。由于环境类的状态存在多样性且在不同状态下对象的行为有所不同,因此将状态独立出去形成单独的状态类。在环境类中维护一个抽象状态类State的实例,这个实例定义当前状态,在具体实现时,它是一个State子类的对象。
  2. State(抽象状态类):它用于定义一个接口以封装与环境类的一个特定状态相关的行为。在抽象状态类中声明各种不同状态对应的方法,而在其子类中实现这些方法。由于不同状态下对象的行为可能不同,因此在不同子类中方法的实现可能存在不同,相同的方法可以写在抽象状态类中。
  3. ConcreteState(具体状态类):它是抽象状态类的子类,每个子类实现一个与环境类的一个状态相关的行为。每个具体状态类对应环境类的一个具体状态,不同的具体状态类其行为有所不同。

2.2、代码示例

在状态模式中,将对象在不同状态下的行为封装到不同的状态类中。为了让系统具有更好的灵活性和可扩展性,同时对各状态下的共有行为进行封装,需要对状态进行抽象,引入了抽象状态类角色,其典型代码如下:

/**
 * @Description: 抽象状态
 * @Author: yangyongbing
 * @CreateTime: 2023/08/03
 * @Version: 1.0
 */
abstract class State {
    // 声明抽象业务方法,不同的具体状态类可以有不同的方法实现
    public abstract void handle();
}

在抽象状态类的子类即具体状态类中实现了在抽象状态类中声明的业务方法,不同的具体状态类可以提供完全不同的方法实现。在实际使用时,一个状态类中可能包含多个业务方法。如果在具体状态类中某些业务方法的实现完全相同,可以将这些方法移至抽象状态类,实现代码的复用。典型的具体状态类代码如下:

/**
 * @Description: 具体状态
 * @Author: yangyongbing
 * @CreateTime: 2023/08/03  19:45
 * @Version: 1.0
 */
public class ConcreteState extends State{
    @Override
    public void handle() {
        // 方法具体实现
    }
}

环境类维持一个对抽象状态类的引用。通过setState()方法可以向环境类注入不同的状态对象,再在环境类的业务方法中调用状态对象的方法,典型代码如下:

/**
 * @Description: 环境类
 * @Author: yangyongbing
 * @CreateTime: 2023/08/03  19:46
 * @Version: 1.0
 */
public class Context {
    // 持有一个对抽象状态对象的引用
    private State state;
    // 其它属性值,该属性值的变化可能会导致对象状态发生变化
    private int value;

    // 设置状态对象
    public void setState(State state) {
        this.state = state;
    }

    public void request(){
        // 其它代码
        state.handle(); // 调用状态对象的业务方法
        // 其他代码
    }
}

环境类实际上是真正拥有状态的对象,这里只是将环境类中与状态有关的代码提取出来封装到专门的状态类中。

在状态模式的使用过程中,一个对象的状态之间还可以进行相互转换。通常有以下两种实现状态转换的方式:

  1. 统一由环境类来负责状态之间的转换。此时,环境类还充当了状态管理器(State Manager)角色。在环境类的业务方法中通过对某些属性值的判断实现状态转换,还可以提供一个专门的方法用于实现属性判断和状态转换。代码片段如下:
public void changeState(){
   // 判断属性值,根据属性值进行状态转换
   if(value==0){
      this.setState(new ConcreteStateA());
   }else if(value==1){
       this.setState(new ConcreteStateB());
   }
}
  1. 由具体状态类来负责状态之间的转换。可以在具体状态类的业务方法中判断环境类的某些属性值再根据情况为环境类设置新的状态对象,实现状态转换。同样,也可以提供一个专门的方法来负责属性值的判断和状态转换。此时,状态类与环境类之间将存在依赖或关联关系,因为状态类需要访问环境类中的属性值。代码片段如下:
public void changeState(Context ctx){
   // 判断属性值,根据属性值进行状态转换
   if(ctx.getValue()==1){
      this.setState(new ConcreteStateB());
   }else if(ctx.getValue()==2){
       this.setState(new ConcreteStateC());
   }
}

2.3、共享状态

在有些情况下,多个环境对象可能需要共享同一个状态。如果希望在系统中实现多个环境对象共享一个或多个状态对象,那么需要将这些状态对象定义为环境类的静态成员对象。

下面通过一个简单实例来说明如何实现共享状态。如果某系统要求两个开关对象要么都处于开的状态,要么都处于关的状态,在使用时它们的状态必须保持一致。开关可以由开转换到关,也可以由关转换到开。

可以使用状态模式来实现开关的设计,其结构如下图所示:
状态模式——对象状态及其转换,设计模式,状态模式

3、状态模式总结

状态模式将一个对象在不同状态下的不同行为封装在一个个状态类中。通过设置不同的状态对象可以让环境对象拥有不同的行为,而状态转换的细节对于客户端而言是透明的,方便了客户端的使用。在实际开发中,状态模式具有较高的使用频率,在工作流、游戏等软件中状态模式都得到了广泛应用,例如公文状态的转换、游戏中角色的升级等。文章来源地址https://www.toymoban.com/news/detail-632128.html

3.1、主要优点

  1. 封装了状态的转换规则。在状态模式中可以将状态的转换代码封装在环境类或者具体状态类中,对状态转换代码进行集中管理,而不是分散在一个个业务方法中。
  2. 将所有与某个状态有关的行为放到一个类中,只需要注入一个不同的状态对象即可使环境对象拥有不同的行为。
  3. 允许状态转换逻辑与状态对象合成一体,而不是提供一个巨大的条件语句块。状态模式可以避免使用庞大的条件语句来将业务方法和状态转换代码交织在一起。
  4. 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

3.2、主要缺点

  1. 状态模式的使用必然会增加系统中类和对象的个数,导致系统运行开销增大。
  2. 状态模式的程序结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,增加系统设计的难度。
  3. 状态模式对开闭原则的支持并不太好。增加新的状态类需要修改那些负责状态转换的源代码,否则无法转换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

3.3、使用场景

  1. 对象的行为依赖于它的状态(例如某些属性值),状态的改变将导致行为的变化。
  2. 在代码中包含大量与对象状态有关的条件语句。这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,并且导致客户类与类库之间的耦合增强。

到了这里,关于状态模式——对象状态及其转换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式(18):状态模式

    用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题 环境类(Context): 环境类中维护一个State对象,它定义了当前的状态,并委托当前状态处理一些请求; 抽象状态类(State): 用于封装对象的一个特定状态所对应的行为; 具体状态类(ConcreteState): 实现了抽象状态类

    2024年04月09日
    浏览(32)
  • 《设计模式》状态模式

    定义 : 状态模式也称为状态机模式, 允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。 属于 行为型 模式。 状态模式的角色组成 : State(抽象状态类) :定义一个接口用来封装与环境类的一个特定状态相关的行为,可以有一个或多个行为。 Con

    2024年02月05日
    浏览(28)
  • 设计模式_状态模式

    介绍 设计模式 定义 案例 问题堆积在哪里 解决办法 状态模式 一个对象 状态可以发生改变 不同的状态又有不同的行为逻辑 游戏角色 加载不同的技能 每个技能有不同的:攻击逻辑 攻击范围 动作等等 1 状态很多 2 每个状态有自己的属性和逻辑 每种状态单独写一个类 角色需要

    2024年02月06日
    浏览(28)
  • 【设计模式】订单状态流传中的状态机与状态模式

    状态模式一般是用在对象内部的 状态流转 场景中,用来实现 状态机 。 什么是状态机呢? 状态机是对状态转移的抽象,由 事件 、 状态 、 动作 组成,事件有时候也被称为 转移事件 或者 转移 ,当事件触发时,可以将状态由一个状态变更为另一个状态,并执行动作。其中,

    2024年02月12日
    浏览(31)
  • 设计模式浅析(十一) ·状态模式

    日常叨逼叨 java设计模式浅析,如果觉得对你有帮助,记得一键三连,谢谢各位观众老爷😁😁 状态模式 概念 状态模式 Java中的状态模式(State Pattern)是一种行为型设计模式,它允许一个对象在其内部状态改变时改变它的行为,看起来就像修改了它的类一样。状态模式的核心

    2024年04月12日
    浏览(26)
  • 设计模式再探——状态模式

    最近产品中有这样的业务需求,不同时间(这里不是活动的执行时间,而是活动的执行时刻)展示不同的活动; 要求还是需要后续会由N种活动扩充进来,并且扩充的时候还得达到复用之前活动中的一些属性和方法。 结合这样的需求,再探状态模式,豁然开朗,于是乎总结分享

    2024年02月16日
    浏览(29)
  • 设计模式行为型-状态模式

    状态模式是一种行为型设计模式,用于处理对象在不同状态下的行为变化。它将对象的行为封装在不同状态类中,通过状态的切换实现不同行为的触发。 本文将介绍状态模式的基本概念、应用场景以及优势与适用性。 实现具体状态类 具体工作类: 上下文类包含状态对象的引

    2024年02月10日
    浏览(33)
  • Java设计模式-状态模式

    在软件开发领域,设计模式是一组经过验证的、被广泛接受的解决问题的方案。其中之一是状态模式,它提供了一种优雅的方式来管理对象的不同状态。 状态模式是一种行为型设计模式,它允许对象在内部状态发生改变时改变其行为。状态模式将对象的行为封装在不同的状态

    2024年02月06日
    浏览(35)
  • 设计模式之状态模式笔记

    记录下学习设计模式-状态模式的写法。JDK使用版本为1.8版本。 意图 :允许一个对象在其内部状态改变时改变它的行为。 结构 : 其中: Context(上下文)定义客户感兴趣的接口;维护一个ConcreteState子类的实例,这个实例定义当前状态。 State(状态)定义一个接口以封装与Context的一个

    2024年02月10日
    浏览(45)
  • 设计模式之状态模式(下)

    3)共享状态 1.概述 在某些情况下,多个环境对象可能需要共享同一个状态,如果希望在系统中实现多个环境对象共享一个或多个状态对象,那么需要将这些状态对象定义为环境类的静态成员对象。 2.案例 背景 :要求两个开关对象要么都处于开的状态,要么都处于关的状态,

    2024年04月25日
    浏览(22)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包