设计模式之状态模式笔记

news2025/1/12 0:02:25

设计模式之状态模式笔记

  • 说明
  • State(状态)
  • 目录
  • 状态模式示例类图
    • 抽象状态类
    • 环境角色类
    • 电梯开启状态类
    • 电梯关闭状态类
    • 电梯运行状态类
    • 电梯停止状态类
    • 测试类

说明

记录下学习设计模式-状态模式的写法。JDK使用版本为1.8版本。

State(状态)

意图:允许一个对象在其内部状态改变时改变它的行为。
结构:
在这里插入图片描述

其中:

  • Context(上下文)定义客户感兴趣的接口;维护一个ConcreteState子类的实例,这个实例定义当前状态。
  • State(状态)定义一个接口以封装与Context的一个特定状态相关的行为。
  • ConcreteState(具体状态子类)每个子类实现与Context的一个状态相关的行为。

适用性:

  • 一个对象的行为决定于它的状态,并且它必须在运行时刻根据状态改变它的行为。
  • 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。

目录

在这里插入图片描述

状态模式示例类图

[例]通过按钮来控制一个电梯的状态,一个电梯有开门状态,关门状态,停止状态,运行状态。每一种状态改变,都有可能要根据其他状态来更新处理。例如,如果电梯门现在处于运行时状态,就不能进行开门操作,而如果电梯门是停止状态,就可以执行开门操作。
在这里插入图片描述

以该UML类图实现状态模式示例。

抽象状态类

package com.example.deesign_patterns.state;

//抽象状态类
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();
}

环境角色类

package com.example.deesign_patterns.state;

//环境角色类
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();
    }
}

电梯开启状态类

package com.example.deesign_patterns.state;

//电梯开启状态类
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() {
        //因为要开启,还没到停止所以什么都不做
    }
}

电梯关闭状态类

package com.example.deesign_patterns.state;

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

    //电梯门关闭再打开,很合理
    @Override
    public void open() {
        //修改状态
        super.context.setLiftState(Context.OPENING_STATE);
        //调用当前状态中的context中的open方法
        super.context.open();
    }

    //当前状态要执行的方法
    @Override
    public void close() {
        System.out.println("电梯门关闭。。。");
    }

    //电梯门关了再运行,很合理
    @Override
    public void run() {
        //修改状态
        super.context.setLiftState(Context.RUNNING_STATE);
        //调用当前状态中的context中的run方法
        super.context.run();
    }

    //电梯门关着,我就不按楼层
    @Override
    public void stop() {
        //修改状态
        super.context.setLiftState(Context.STOPPING_STATE);
        //调用当前状态中的context中的stop方法
        super.context.stop();
    }
}

电梯运行状态类

package com.example.deesign_patterns.state;

//电梯运行状态类
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);
        //调用当前状态中的context中的stop方法
        super.context.stop();
    }
}

电梯停止状态类

package com.example.deesign_patterns.state;

//电梯停止状态类
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("电梯停止了。。。");
    }
}

测试类

package com.example.deesign_patterns.state;

//测试类
public class Client {

    public static void main(String[] args) {
        //创建环境角色对象
        Context context=new Context();
        //设置当前电梯状态,这里设置为正在运行状态
        context.setLiftState(new RunningState());
        context.open();
        context.close();
        context.run();
        context.stop();
    }
}


在这里插入图片描述

好处:

  • 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
  • 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。

缺点:

  • 状态模式的使用必然会增加系统类和对象的个数。
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
  • 状态模式对开闭原则的支持并不太好。

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

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

相关文章

从零搭建一台基于ROS的自动驾驶车-----4.定位

系列文章目录 北科天绘 16线3维激光雷达开发教程 基于Rplidar二维雷达使用Hector_SLAM算法在ROS中建图 Nvidia Jetson Nano学习笔记–串口通信 Nvidia Jetson Nano学习笔记–使用C语言实现GPIO 输入输出 Autolabor ROS机器人教程 从零搭建一台基于ROS的自动驾驶车-----1.整体介…

【Leetcode60天带刷】day25回溯算法——216.组合总和III,17.电话号码的字母组合

​ 题目: 216. 组合总和 III 找出所有相加之和为 n 的 k 个数的组合,且满足下列条件: 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。 示例 1…

读书笔记--数据治理之术

继延续上一篇文章,对数据治理之术进行学习思考,这部分内容是本书整体内容的核心细节,内容比较多比较杂,通读了好长时间才动手总结整理,因此更新的慢了一些。数据治理之术是操作层面的技术或方法,数据治理相…

linux系统如何添加硬盘设备

前言: 今天记录一下硬盘方面的知识,主要讲一下分区、挂载方面的知识,心情太郁闷了,假期的最后一天。 1、硬盘的命名规则 现在的硬盘设备一般都会以“/dev/sd”开头,而一台主机上可以有多块硬盘设备,因此系…

6.24全球央行鹰派立场重现,下周黄金是否会继续下跌?

近期有哪些消息面影响黄金走势?下周黄金多空该如何研判? ​黄金消息面解析:周五(6月23日)美市尾盘,现货黄金收报1920.44美元/盎司,上升6.58美元或0.34%,日内最高触及1937.46美元/盎…

Linux基础服务3——samba

文章目录 一、基本了解1.1 服务安装1.2 服务进程和端口1.3 samba用户1.4 配置文件1.4.1 主配置文件1.4.2 配置文件参数 1.5 安全级别 二、访问samba2.1 参数测试2.2 交互式访问2.3 挂载访问2.3.1 临时挂载2.3.2 永久挂载 2.4 配置用户认证共享2.5 匿名共享 一、基本了解 什么是…

VS Code基于服务器中的docker的开发环境配置

VS Code基于服务器中的docker的开发环境配置 基于Dev Containers插件基于Jump Machine(跳板机)服务器通过ssh连接docker容器VS Code配置ssh config文件连接docker容器 基于Dev Containers插件 当然可以在vscode中直接下载Dev Containers插件&#xff0c…

表上作业法一般流程(最小元素法、闭合回路法、位势法)

目录 一、列出物资调运平衡表和运价表 二、编制初始调运方案 三、初始方案的检验与调整 1)闭合回路法 2)位势法 3)调整调运方案 表上作业法一般步骤: ①列出调运物资的供需(产销)平衡表及运价表; ②按最小元素…

mediapipe 谷歌高效ML框架-图像识别、人脸检测、人体关键点检测、手部关键点检测

参考: https://github.com/google/mediapipe https://developers.google.com/mediapipe/solutions/guide 框架也支持cv、nlp、audio等项目,速度很快: 1、图形识别 参考:https://developers.google.com/mediapipe/solutions/vi…

05.内存管理:动态申请和释放内存

动态分配内存,进行内存管理 参考: 伙伴算法原理简介 linux 0.11源码 本文主要针对Linux0.11的malloc和free进行分析。是一种类似伙伴系统的内存管理方法,不过伙伴系统的内存通常是申请大于一页的内存,但是在该内核版本的内存管理&#xff0c…

剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 / LeetCode 235. 二叉搜索树的最近公共祖先(二叉搜索树性质,搜索与回溯)

题目: 链接:剑指 Offer 68 - I. 二叉搜索树的最近公共祖先;LeetCode 235. 二叉搜索树的最近公共祖先 难度:中等 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对…

redis存储原理与数据模型学习笔记

目录 1 redis线程模型1.1 线程组成1.2 redis命令处理是单线程 2 redis db 存储分析2.1 先了解代码server.hdict.h 2.2 从kv存储分析2.3 负载因子2.4 渐进式rehash机制数据访问scan 3 数据模型分析以zset为例跳表 1 redis线程模型 1.1 线程组成 redis-server 命令处理 网络事件…

Nerf论文前后介绍以及今后方向(2020年各个方向工作论文分析) NEURAL VOLUME RENDERING:NERF AND BEYOND

你好! 这里是“出门吃三碗饭”本人, 本文章接下来将介绍2020年对Nerf工作的一篇总结论文NEURAL VOLUME RENDERING:NERF AND BEYOND,论文作者是佐治亚理工学院的Frank Dellaert同学和 MIT的Lin Yen-Chen同学,非常感谢两位大佬的总结…

序列化和反序列化的认识【protobuf、json、xml】

1. 什么是序列化与反序列化? 程序员在编写应用程序的时候往往需要将程序的某些数据存储在连续的内存中,然后将其写入文件或是将其传输到网络中的另一台计算机上以实现通讯。这个将程序数据转换成能被存储并传输的格式的过程被称为序列化(seri…

C++ array (STL array) 序列容器

文章目录 1 类模板2 begin()/end() 和 cbegin()/cend()3 cbegin() 和 cend()4 rbegin()/rend() 和 crbegin()/crend()5 访问array容器中单个元素参考 1 类模板 array 容器以类模板的形式定义在 头文件,并位于命名空间 std 中,如下所示: nam…

一、约束编程简介(Constraints Programming)

文章目录 1、约束编程求解器2、值域传播器THE END 1、约束编程求解器 \qquad 约束编程是一种编程范式,旨在解决那些需要满足一系列约束条件的问题。在约束编程中,问题被定义为一组变量和约束条件,而不是指定解决问题的算法步骤。通过定义变量…

XXE漏洞复现步骤

0X00XXE注入定义 XXE注入,即XML External Entity,XML外部实体注入。通过 XML 实体,”SYSTEM”关键词导致 XML 解析器可以从本地文件或者远程 URI 中读取数据。所以攻击者可以通过 XML 实体传递自己构造的恶意值,是处理程序解析它…

Nginx-负载均衡详解

本文已收录于专栏 《中间件合集》 目录 概念说明什么是Nginx什么是负载均衡 功能介绍配置过程1.修改nginx配置文件添加服务组修改HTTP模块 2.保存配置文件3.重启配置文件4.查看配置文件是否重启成功5.还可以配置其他策略轮询权重最少连接数 常用命令总结提升 概念说明 了解ngi…

MySQL:环境安装和数据库基础

环境安装 说明: • 安装与卸载中,用户全部切换成为root,⼀旦 安装,普通用户能使⽤的 • 初期练习,mysql不进行用户管理,全部使⽤root进行,尽快适应mysql语句,后⾯学了用户管 理&a…

实例讲解,一文弄懂workqueue和waitqueue

本期主题: 讲清workqueue和waitqueu: 从中断讲起waitqueue是什么workqueue总结 往期链接: linux设备驱动中的并发linux设备驱动中的编译乱序和执行乱序linux设备驱动之内核模块linux字符驱动linux字符驱动之ioctl部分linux字符驱动之read、…