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

目录

        • 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;@Overridepublic void setState(int state) {this.state = state;}@Overridepublic 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;}}@Overridepublic 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;}}@Overridepublic 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;}}@Overridepublic 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 {// 当前状态要执行的方法@Overridepublic void open() {System.out.println("电梯开启");}@Overridepublic void close() {// 修改状态super.context.setLiftState(Context.CLOSING_STATE);// 调用当前状态中的context中的close方法super.context.close();}@Overridepublic void run() {// 什么都不做}@Overridepublic void stop() {// 什么都不做}
}
  • 2.运行状态类
package com.learning.state.after;/**
* 运行状态类
*/
public class RunningState extends LiftState {/*** 运行的时候是不能开电梯门*/@Overridepublic void open() {// 什么都不做}/*** 运行状态的电梯,门不需要再关*/@Overridepublic void close() {// 什么都不做}/*** 运行状态下要实现的方法*/@Overridepublic void run() {System.out.println("电梯正在运行");}/*** 运行状态可以停止*/@Overridepublic void stop() {super.context.setLiftState(Context.STOPPING_STATE);super.context.stop();}
}
  • 3.停止状态类
package com.learning.state.after;/*** 停止状态类*/
public class StoppingState extends LiftState {/*** 停止状态可以开门*/@Overridepublic void open() {// 状态修改super.context.setLiftState(Context.OPENING_STATE);// 动作委托为CloseState来执行,也就是委托给ClosingState子类执行这个动作super.context.getLiftState().open();}/*** 可以关门,这个动作不归我执行*/@Overridepublic void close() {// 状态修改super.context.setLiftState(Context.CLOSING_STATE);// 动作委托为CloseState来执行,也就是委托给ClosingState子类执行这个动作super.context.getLiftState().close();}/*** 停止后,可以再跑起来*/@Overridepublic void run() {// 状态修改super.context.setLiftState(Context.RUNNING_STATE);// 动作委托为CloseState来执行,也就是委托给ClosingState子类执行这个动作super.context.getLiftState().run();}/*** 停止方法执行*/@Overridepublic void stop() {System.out.println("电梯停止了");}
}
  • 4.关闭状态类
package com.learning.state.after;/*** 关闭状态类*/
public class ClosingState extends LiftState {/*** 电梯关闭状态可以再打开*/@Overridepublic void open() {super.context.setLiftState(Context.OPENING_STATE);super.context.open();}/*** 电梯关闭状态实现的动作*/@Overridepublic void close() {System.out.println("电梯门关闭");}/*** 电梯关门之后启动*/@Overridepublic void run() {super.context.setLiftState(Context.RUNNING_STATE);super.context.run();}/*** 电梯门关着,但没按楼层*/@Overridepublic 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.mzph.cn/news/772732.shtml

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

相关文章

ArcGIS矢量裁剪矢量

一、利用相交工具 Arctoolbox工具一分析工具一叠加分析一相交

react native

简介 React Native 就是使用React和应用平台的原生功能来构建 Android 和 iOS 应用的开源框架。在 Android 和 iOS 开发中,一个视图是 UI 的基本组成部分,React 组件通过 JavaScript 来调用这些视图。可以构建自己的 Native Components(原生组件)&#…

C# wpf 嵌入hwnd窗口

WPF Hwnd窗口互操作系列 第一章 嵌入Hwnd窗口(本章) 第二章 嵌入WinForm控件 第三章 嵌入WPF控件 文章目录 WPF Hwnd窗口互操作系列前言一、如何实现1、继承HwndHost2、实现抽象方法3、xaml中使用HwndHost控件 二、具体实现1、Win32窗口2、HwndSource窗…

思腾合力出席文化和旅游虚拟现实应用推广交流活动并作主题演讲

3月21日,由文化和旅游部产业发展司主办,中国信息通信研究院、北京市石景山区文化和旅游局、中国动漫集团有限公司承办的“数字赋能文旅场景建设行动——文化和旅游虚拟现实应用推广交流活动”在北京首钢一高炉SoReal科幻乐园成功举办。 思腾合力CMO徐莉受…

【第028篇】用IDEA打开并运行Eclipse创建的项目

下图我使用的是2021版本的idea 一、 导入 首先,点击左上方【File】-【New】-【Project from Existing Sources】 在目录中选择自己要导入的eclipse动态项目; 3、这里选择【import project from external model】,再选择【eclipse】&#…

【jenkins+cmake+svn管理c++项目】Windows环境安装以及工具配置

一、目标和环境 目标:搭建一个jenkins环境,实现jenkins调用cmake和svn和VS编译c项目,并将生成的库上传svn。 环境:win10虚拟机(练习流程用,正式用的话还是放到服务器),VS2017. 二、…

Flask python :logging日志功能使用

logging日志的使用 一、了解flask日志1.1、Loggers记录器1.2、Handlers 处理器1.3、Formatters 格式化器 二、使用日志2.1、官网上的一个简单的示例2.2、基本配置2.3、具体使用示例2.4、运行 三、写在最后 一、了解flask日志 日志是一种非常重要的工具,可以帮助开发…

pandas 函数

pandas是基于numpy数组构建的,但二者最大的不同是pandas是专门为处理表格和混杂数据设计的,比较契合统计分析中的表结构,而numpy更适合处理统一的数值数组数据。pandas数组结构有一维Series和二维DataFrame。 Series的字符串表现形式为&#…

java Web线上网游商品交易平台用eclipse定制开发mysql数据库BS模式java编程jdbc

一、源码特点 jsp线上网游商品交易平台是一套完善的web设计系统,对理解JSP java SERLVET mvc编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为TOMCAT7.0,eclipse开发,数据库为Mysql5.0…

基于springboot的交通管理在线服务系统的开发

传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装交通管理在线服务系统软件来发挥其高效地信息处理的作用&#xff0…

【数据结构】常见线性结构

1.线性表 线性表 ( linear list ) 是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构,也就说是连续的一…

Fiddler抓包工具之fiddler的常用快捷键

一、常用三个快捷键 ctrlX :清空所有记录 CtrlF:查找 F12:启动或者停止抓包 使用 QuickExec Fiddler2 成了网页调试必备的工具,抓包看数据。Fiddler2自带命令行控制。 fiddler 命令行快捷键:ctrl q ,然后 输入 help…

约瑟夫环问题(队列,链表实现)- c++

1.关于约瑟夫问题 约瑟夫斯领导犹太人反抗罗马帝国的统治,在与罗马军队的激烈战斗中,与士兵们一同被困在一个山洞里。总共有41人,约瑟夫斯希望向罗马军队投降,但他的士兵们却坚决拒绝,宁愿死也不愿被敌人俘虏。面对这…

国家中英文名称、国家代码(地区代码)、国家域名、经纬度

因为要做世界地图对世界国家的标点,搜索使用到了世界各个国家的地理位置信息,此处做备份与学习。资源地址(免费) export default {"阿尔巴尼亚": {"m_longitude": "19.809","m_latitude&quo…

React项目打包优化-包体积分析

1、什么是包体积分析? 通过可视化的方式,直观的看到各种包打包之后的体积大小,方便后续针对体积情况做优化 2、怎么分析包? 借助插件 source-map-explorer, 1、先安装插件 npm install source-map-explorer 2、在p…

Consul集群搭建看这篇就够了(consul cluster configuration )

Consul 是一种用于服务发现、配置和分布式一致性的开源工具和平台。它由 HashiCorp 公司开发和维护,旨在简化构建和维护分布式系统的任务。 Consul 提供了许多功能,包括: 服务发现:Consul允许服务注册和发现。当服务启动时&#…

JAVA-----

标识符 标识符可以简单的理解为一个名字,在Java中,我们需要给代码中的很多元素起名字,包括类名、方法名、字段名、变量名等等。我们给对应元素起的名称就被叫做是标识符。一个正确的标识符需要遵循以下规则: 1.标识符可以由字母、…

PYTHON初级笔记1

0、python? 简单的编程语言 python环境搭建: ①、开发环境:vscode、sublime、pycharm...... ②、运行环境:cpython解释器 python如何写代码? ①、在终端上的命令行上写,可以是我们cmd的中终端,…

MATLAB 公共区域的点云合并(46)

MATLAB 公共区域的点云合并(46) 一、算法介绍二、算法实现1.代码2.效果一、算法介绍 点云配准后,或者公共区域存在多片点云对场景进行冗余过量表达时,我们需要将点云进行合并,Matlab点云工具中提供了这样的合并函数,通过指定网格步长,对初始点云进行过滤。 函数主要实…

分治——快速排序算法

例题一 解法(快排思想 - 三指针法使数组分三块): 算法思路: 类⽐数组分两块的算法思想,这⾥是将数组分成三块,那么我们可以再添加⼀个指针,实现数组分 三块。 设数组⼤⼩为 n &#xff0c…