【软考】设计模式之状态模式

news2024/12/29 17:40:53

目录

        • 1. 说明
        • 2. 应用场景
        • 3. 结构图
        • 4. 构成
        • 5. 优缺点
          • 5.1 优点
          • 5.2 缺点
        • 6. java示例
          • 6.1 非状态模式
            • 6.1.1 问题分析
            • 6.1.2 接口类
            • 6.1.2 实现类
            • 6.1.3 客户端
            • 6.1.4 结果截图
          • 6.2 状态模式
            • 6.2.1 抽象状态类
            • 6.2.2 状态类
            • 6.2.3 上下文类
            • 6.2.4 上下文类

1. 说明
  • 1.允许一个对象在其内部状态改变时改变它的行为。
  • 2.对象看起来似乎修改了它的类。
  • 3.对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
2. 应用场景
  • 1.一个对象的行为决定于它的状态,并且它必须在运行时刻根据状态改变它的行为。
  • 2.一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得开发者可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象独立变化。
3. 结构图

在这里插入图片描述

4. 构成
  • 1.环境角色:Context(上下文)定义客户端感兴趣的接口;维护一个ConcreteState子类的实例,这个实例定义当前状态
  • 2.抽象状态角色:State(状态)定义一个接口以封装与Context的一个特定状态相关的行为
  • 3.具体状态角色:ConcreteState(具体状态子类)每个子类实现与Context的一个状态相关的行为
5. 优缺点
5.1 优点
  • 1.将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
  • 2.允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
5.2 缺点
  • 1.状态模式的使用必然会增加系统类和对象的个数。
  • 2.状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
  • 3.状态模式对"开闭原则"的支持并不太好。
6. java示例
6.1 非状态模式
6.1.1 问题分析
  • 1.使用了大量的switch case这样的判断(if else也是一样),使程序的可阅读性变差
  • 2.扩展性差,如果新加了一种状态,则需要修改判断逻辑
6.1.2 接口类
package com.learning.state.before;

/**
 * 电梯接口
 */
public interface ILift {
    //定义四个电梯状态的常量

    /**
     * 打开状态
     */
    int OPENING_STATE = 1;
    /**
     * 关闭状态
     */
    int CLOSING_STATE = 2;
    /**
     * 运行状态
     */
    int RUNNING_STATE = 3;
    /**
     * 停止状态
     */
    int STOPPING_STATE = 4;

    //设置电梯状态的功能
    void setState(int state);

    //电梯操作功能
    void open();

    //电梯关闭功能
    void close();

    //电梯运行功能
    void run();

    //电梯停止功能
    void stop();
}

6.1.2 实现类
package com.learning.state.before;

/**
 * @Description 电梯类
 **/
public class Lift implements ILift{
    //当前电梯状态
    private int state;

    @Override
    public void setState(int state) {
        this.state = state;
    }

    @Override
    public void open() {
        switch(state){
            //如果当前电梯状态是开启状态
            case OPENING_STATE:
                //什么都不做
                break;
            //如果当前电梯状态是关闭状态,打开电梯
            case CLOSING_STATE:
                System.out.println("电梯打开了");
                // 设置当前电梯状态为开启状态
                setState(OPENING_STATE);
                break;
            //如果当前电梯状态是运行状态
            case RUNNING_STATE:
                //什么都不做
                break;
            //如果当前电梯状态是开启状态,打开电梯
            case STOPPING_STATE:
                System.out.println("电梯打开了");
                setState(OPENING_STATE);
                break;

        }
    }

    @Override
    public void close() {
        switch(this.state) {
            case OPENING_STATE:
                //只有开门状态可以关闭电梯门
                System.out.println("电梯关门了");
                //关门之后电梯就是关闭状态了
                this.setState(CLOSING_STATE);
                break;
            case CLOSING_STATE:
                //已经是关门状态,不能关门
                //什么都不做
                break;
            case RUNNING_STATE:
                //运行时电梯门是关着的,不能关门
                //什么都不做
                break;
            case STOPPING_STATE:
                //停止时电梯也是关着的,不能关门
                //什么都不做
                break;
        }
    }

    @Override
    public void run() {
        switch(this.state) {
            case OPENING_STATE:
                //电梯不能开着门运行
                break;
            case CLOSING_STATE:
                //门关了,可以运行了
                System.out.println("电梯运行了");
                //设置为运行状态
                this.setState(RUNNING_STATE);
                break;
            case RUNNING_STATE:
                //已经是运行状态了
                break;
            case STOPPING_STATE:
                System.out.println("电梯运行了");
                //设置为运行状态
                this.setState(RUNNING_STATE);
                break;
        }
    }

    @Override
    public void stop() {
        switch(this.state) {
            case OPENING_STATE:
                // 开门的电梯已经是是停止的了(正常情况下)
                break;
            case CLOSING_STATE:
                // 关门时才可以停止
                System.out.println("电梯停止了");
                this.setState(STOPPING_STATE);
                break;
            case RUNNING_STATE:
                // 运行时当然可以停止了
                System.out.println("电梯停止了");
                this.setState(STOPPING_STATE);
                break;
            case STOPPING_STATE:
                break;
        }
    }
}

6.1.3 客户端
package com.learning.state.before;

/**
 * 客户端
 */
public class Client {
    public static void main(String[] args) {
        // 创建电梯对象
        Lift lift = new Lift();
        // 设置当前电梯的状态
        lift.setState(ILift.OPENING_STATE);

        // 打开
        lift.open();

        lift.close();
        lift.run();
        lift.stop();
    }
}
6.1.4 结果截图

在这里插入图片描述

6.2 状态模式
6.2.1 抽象状态类
package com.learning.state.after;

/**
 * 抽象状态类
 */
public abstract class LiftState {

    // 声明环境角色类变量
    protected Context context;

    public void setContext(Context context){
        this.context = context;
    }

    // 电梯开启操作
    public abstract void open();

    // 电梯关闭操作
    public abstract void close();

    // 电梯运行操作
    public abstract void run();

    // 电梯停止操作
    public abstract void stop();
}

6.2.2 状态类
  • 1.开启状态类
package com.learning.state.after;

/**
 * 开启状态类
 */
public class OpeningState extends LiftState {
    // 当前状态要执行的方法
    @Override
    public void open() {
        System.out.println("电梯开启");
    }

    @Override
    public void close() {
        // 修改状态
        super.context.setLiftState(Context.CLOSING_STATE);
        // 调用当前状态中的context中的close方法
        super.context.close();
    }

    @Override
    public void run() {
        // 什么都不做
    }

    @Override
    public void stop() {
        // 什么都不做
    }
}
  • 2.运行状态类
package com.learning.state.after;

/**
* 运行状态类
*/
public class RunningState extends LiftState {

   /**
    * 运行的时候是不能开电梯门
     */
   @Override
   public void open() {
       // 什么都不做
   }

   /**
    * 运行状态的电梯,门不需要再关
     */
   @Override
   public void close() {
       // 什么都不做
   }

   /**
    * 运行状态下要实现的方法
    */
   @Override
   public void run() {
       System.out.println("电梯正在运行");
   }

   /**
    * 运行状态可以停止
    */
   @Override
   public void stop() {
       super.context.setLiftState(Context.STOPPING_STATE);
       super.context.stop();
   }
}

  • 3.停止状态类
package com.learning.state.after;

/**
 * 停止状态类
 */
public class StoppingState extends LiftState {

    /**
     * 停止状态可以开门
     */
    @Override
    public void open() {
        // 状态修改
        super.context.setLiftState(Context.OPENING_STATE);
        // 动作委托为CloseState来执行,也就是委托给ClosingState子类执行这个动作
        super.context.getLiftState().open();
    }

    /**
     * 可以关门,这个动作不归我执行
     */
    @Override
    public void close() {
        // 状态修改
        super.context.setLiftState(Context.CLOSING_STATE);
        // 动作委托为CloseState来执行,也就是委托给ClosingState子类执行这个动作
        super.context.getLiftState().close();
    }

    /**
     * 停止后,可以再跑起来
     */
    @Override
    public void run() {
        // 状态修改
        super.context.setLiftState(Context.RUNNING_STATE);
        // 动作委托为CloseState来执行,也就是委托给ClosingState子类执行这个动作
        super.context.getLiftState().run();
    }

    /**
     * 停止方法执行
     */
    @Override
    public void stop() {
        System.out.println("电梯停止了");
    }
}

  • 4.关闭状态类
package com.learning.state.after;

/**
 * 关闭状态类
 */
public class ClosingState extends LiftState {

    /**
     * 电梯关闭状态可以再打开
     */
    @Override
    public void open() {
        super.context.setLiftState(Context.OPENING_STATE);
        super.context.open();
    }

    /**
     * 电梯关闭状态实现的动作
     */
    @Override
    public void close() {
        System.out.println("电梯门关闭");
    }

    /**
     * 电梯关门之后启动
     */
    @Override
    public void run() {
        super.context.setLiftState(Context.RUNNING_STATE);
        super.context.run();
    }

    /**
     * 电梯门关着,但没按楼层
     */
    @Override
    public void stop() {
        super.context.setLiftState(Context.STOPPING_STATE);
        super.context.stop();
    }
}
6.2.3 上下文类
package com.learning.state.after;

public class Context {

    // 定义对应状态对象的常量
    public final static OpeningState OPENING_STATE = new OpeningState();

    public final static ClosingState CLOSING_STATE = new ClosingState();

    public final static RunningState RUNNING_STATE = new RunningState();

    public final static StoppingState STOPPING_STATE = new StoppingState();

    // 定义一个当前电梯状态变量
    private LiftState liftState;

    public LiftState getLiftState(){
        return liftState;
    }

    public void setLiftState(LiftState liftState){
        this.liftState = liftState;
        // 设置当前状态对象中的Context对象
        this.liftState.setContext(this);
    }

    public void open(){
        this.liftState.open();
    }

    public void close(){
        this.liftState.close();
    }

    public void run(){
        this.liftState.run();
    }

    public void stop(){
        this.liftState.stop();
    }

}

6.2.4 上下文类
package com.learning.state.after;

/**
 * 客户端类
 */
public class Client {
    public static void main(String[] args) {
        // 创建环境角色对象
        Context context = new Context();
        // 设置当前电梯状态
        context.setLiftState(Context.CLOSING_STATE);

        context.open();
        context.close();
        context.run();
        context.stop();

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1547129.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pycharm使用远程服务器的jupyter环境

1、确保服务器上安装了jupyter,如果没有,执行下面命令安装 pip install jupyter2、启动jupyter notebook服务 jupyter notebook --no-browser --port8888 --ip0.0.0.0 --allow-root表明在服务器的8888 端口上启动 Jupyter Notebook,并允许从任何 IP 地…

阿里云ESC云服务器搭建手册

1.开通阿里云ESC云服务 1.1 打开阿里云官网 https://www.aliyun.com/ 自行注册登录 1.2 选择产品 1.3 点击免费试用 新用户可以免费试用3个月 1.4 选择服务器配置 1.5 选择操作系统 创建服务器实例的时候会自动帮我们创建一个操作系统 1.6 点击立即试用 1.7 创建成功后点击前往…

鸿蒙HarmonyOS应用开发——组件级配置

在开发应用时,需要配置应用的一些标签,例如应用的包名、图标等标识特征的属性。本文描述了在开发应用需要配置的一些关键标签。 应用包名配置 应用需要在工程的AppScope目录下的 app.json5配置文件 中配置bundleName标签,该标签用于标识应用…

《MobileFaceNet:一种用于移动设备实时人脸验证的高效CNN》论文阅读

最近正好做到人脸识别的一点工作,在查阅资料的时候看到了这篇文章,就想花点时间来读一下。这里是自己的阅读记录,英语水平不够借助翻译软件来读的,感兴趣可以看下,也可以自行阅读原始英文论文。 摘要 我们提出了一类非…

企业级快速开发框架 nbsaas-boot 1.1.8-2024 发布了

<parent><groupId>com.nbsaas.boot</groupId><artifactId>nbsaas-boot</artifactId><version>1.1.8-2024</version> </parent> 本次更新内容 1. 重构代码生成器&#xff0c;采用类提取和字段提取两种方式&#xff0c;提取功能…

神经网络代码实现(用手写数字识别数据集实验)

目录 一、前言 二、神经网络架构 三、算法实现 1、导入包 2、实现类 3、训练函数 4、权重参数矩阵初始化 5、参数矩阵变换向量 6、向量变换权重参数矩阵 7、进行梯度下降 7.1、损失函数 7.1.1、前向传播 7.2、反向传播 8、预测函数 四、完整代码 五、手写数字识别 一、前言 …

R语言神经网路模型应用(1)

数据集heart_learning.csv与heart_test.csv是关于心脏病的数据集&#xff0c;heart_learning.csv是训练数据集&#xff0c;heart_test.csv是测试数据集。要求&#xff1a;target和target2为因变量&#xff0c;其他诸变量为自变量&#xff0c;用神经网络模型&#xff08;多层感知…

PC电脑技巧[笔记本通过网线访问设备CMW500]

笔记本局域网访问设备 现在我有一台CMW500,我要用笔记本去访问它,但是我发现没有路由器就是不能够访问,通过网线连接设备就是ping不通: 这里设置TCP/IPv4的IP地址如下,这时候就可以pin通了:

跟张良均老师学大数据人工智能——数据挖掘集训营开营

集训营特色&#xff1a; 知识点深入浅出&#xff0c;实现以学促用 以业务内容为主线&#xff0c;数据挖掘技能嵌入 多行业项目实战&#xff0c;全面提升职业素养 全程线上辅导&#xff0c;助力熟练掌握技能 惊喜优惠&#xff1a; 限时“六折”&#xff01; 师傅带练 方向…

VsCode中安装codeium 显示failed to start language server

一、在VsCode的SSH Remote插件中安装Codeium 失败&#xff1a; 1、在插件Remote Explore中的SSH安装Codeium插件后提示无法下载语言服务器&#xff0c;如下图所示 2、去Codeium的仓库中找到对应版本的语言服务器包下载&#xff0c;然后解压并拷贝到远程服务器Ubuntu中的如下目…

云手机:实现便携与安全的双赢

随着5G时代的到来&#xff0c;云手机在各大游戏、直播和新媒体营销中扮演越来越重要的角色。它不仅节约了成本&#xff0c;提高了效率&#xff0c;而且在边缘计算和云技术逐渐成熟的背景下&#xff0c;展现出了更大的发展机遇。 云手机的便携性如何&#xff1f; 云手机的便携性…

【jenkins+cmake+svn管理c++项目】创建一个项目

工作台点击"新建item",进入下图&#xff0c;选择Freestyle project,并输入项目名称&#xff0c; 点击确定之后进入项目配置页面&#xff0c;填写描述&#xff0c;然后在下边源码管理部分选择svn, 填写代码的url 上图的Credentials处填写svn的有效登录名和密码&#x…

5.1 物联网RK3399项目开发实录-Android开发之ADB使用(wulianjishu666)

物联网项目开发实例&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/11VQMhHfIL9mZhNlls4wmjw?pwd0gfa 1. ADB 使用 1.1. 前言 ADB&#xff0c;全称 Android Debug Bridge&#xff0c;是 Android 的命令行调试工具&#xff0c;可以完成多种功能&#xff0c;如跟踪系…

DP:简单多状态模型

创作不易&#xff0c;感谢三连 多状态DP表示第i天的时候可能的状态不同&#xff0c;所以我们要去区分不同的状态。 一、打家劫舍&#xff08;1&#xff09; . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int rob(vector<int>& nums) {int n…

C++初步认识

一.开发环境 Dev-C是一个Windows环境下的一个适合于初学者使用的轻量级C/C 集成开发环境&#xff08;IDE&#xff09;&#xff0c;它是一款自由软件&#xff0c;遵守GPL许可协议分发源代码。 Dev-C 使用MingW64/TDM-GCC编译器&#xff0c;遵循C 11标准&#xff0c;同时兼容C98标…

jmeter二次开发发送java请求_保姆级教程!!!

一、引言 JMeter是Apache基金会开发的一款开源性能测试工具&#xff0c;广泛应用于软件性能测试领域。它能够模拟多线程并发用户对应用程序进行压力测试&#xff0c;以评估应用程序的性能和稳定性。然而&#xff0c;在实际使用过程中&#xff0c;用户可能会遇到需要发送Java请…

网上国网App启动鸿蒙原生应用开发,鸿蒙开发前景怎么样?

从华为宣布全面启动鸿蒙生态原生应用一来&#xff0c;各种各样的新闻就没有停过&#xff0c;如&#xff1a;阿里、京东、小红书……等大厂的加入&#xff0c;而这次他们又与一个国企大厂进行合作&#xff1a; 作为特大型国有重点骨干企业&#xff0c;国家电网承担着保障安全、经…

Python 全栈体系【四阶】(二十一)

第五章 深度学习 二、推荐系统 2. 协同过滤及实现 2.1 基于物品的协同过滤推荐技术(评分) 2.2 基于物品的协同过滤算法(Item_CF) 2.3 基于用户的协同过滤算法&#xff08;user-based collaboratIve filtering&#xff09; 2.4 基本原理 2.5 ICF 计算物品之间的相似度&#…

Set和Map数据结构

Set和Map数据结构理解 Set&#xff1a; 1、es6新的数据结构&#xff0c;类似数组&#xff0c;但成员唯一 2、实例属性&#xff1a;Set.prototype.size返回Set实例的成员总数 3、操作方法&#xff1a;add、delete、has、clear 4、遍历操作&#xff1a;forEach、keys、values、en…

求两个单链表的差集

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 但行前路&#xff0c;不负韶华&#…