当前位置: 首页 > news >正文

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

目录

        • 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.lryc.cn/news/328376.html

相关文章:

  • MNN介绍、安装与编译:移动端深度学习推理引擎
  • A Simple Problem with Integers(线段树)
  • 单元测试(UT)用例简介
  • Java通过反射机制获取类对象下的属性值
  • IDEA插件开发-File -> New->Project中添加一个myOptions
  • 海量数据处理项目-账号微服务和流量包数据库表+索引规范(下)
  • Nodejs 16与 gitbook搭建属于你自己的书本网站-第一篇
  • 服务器被CC攻击之后怎么办?
  • pygame通过重心坐标 用纹理填充三角形
  • Leetcode 611. 有效三角形的个数
  • Openfeign
  • 五、基于KubeAdm搭建多节点K8S集群
  • PC电脑技巧[笔记本通过网线访问设备CMW500]
  • 【接口自动化测试框架】YAML管理接口框架配置的最佳实践
  • 【进程OI】基本文件操作的系统调用
  • Ubuntu20.04 server系统部署安装(VMware上)和初始化配置
  • 图论最短路径以及floyd算法的MATLAB实现
  • 微信小程序 - 登录功能实现
  • Python连接MySQL
  • 水泊梁山108小酒坛之呼保义宋江
  • java.lang.ClassNotFoundException: javafx.application.Application
  • 腾讯 tendis 替代 redis linux安装使用
  • k8s调优--来自gpt
  • HTML5+CSS3小实例:旋转中的视差效果
  • 3-zookeeper之ZAB协议
  • 如何为企业策划一场XR虚拟直播?
  • 6.3物联网RK3399项目开发实录-驱动开发之I2C 使用(wulianjishu666)
  • HarmonyOS实战开发-如何构建多种样式弹窗
  • 《Effective C++》《构造/析构/赋值运算——7、为多态基类声明virtual析构函数》
  • Type-C一分二快充线智能分配方案