Java设计模式之状态模式

定义

对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。

结构

状态模式包含以下主要角色。

  • 环境角色:也称为上下文,它定义了客户程序需要的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
  • 抽象状态角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。
  • 具体状态角色:实现抽象状态所对应的行为。

案例

环境角色

public class Context {
    public final static OpenningState openningState = new OpenningState();//开门状态,这时候电梯只能关闭
    public final static ClosingState closeingState = new ClosingState();//关闭状态,这时候电梯可以运行、停止和开门
    public final static RunningState runningState = new RunningState();//运行状态,这时候电梯只能停止
    public final static StoppingState stoppingState = new StoppingState();//停止状态,这时候电梯可以开门、运行


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

    public LiftState getLiftState() {
        return this.liftState;
    }

    public void setLiftState(LiftState liftState) {
        //当前环境改变
        this.liftState = liftState;
        //把当前的环境通知到各个实现类中
        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();
    }
}

状态类。用来统一不同状态的执行方法。 

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();
}

创建具体状态角色 

public class StoppingState extends LiftState{
    @Override
    public void open() {
        System.out.println("门开了");
        context.setLiftState(Context.openningState);
    }

    @Override
    public void close() {

    }

    @Override
    public void run() {
        System.out.println("电梯运行了");
        context.setLiftState(Context.runningState);
    }

    @Override
    public void stop() {

    }
}

public class RunningState extends LiftState{
    @Override
    public void open() {

    }

    @Override
    public void close() {

    }

    @Override
    public void run() {

    }

    @Override
    public void stop() {
        System.out.println("电梯停了");
        context.setLiftState(Context.stoppingState);
    }
}

public class ClosingState extends LiftState{
    @Override
    public void open() {
        System.out.println("门打开了");
        context.setLiftState(Context.openningState);
    }

    @Override
    public void close() {

    }

    @Override
    public void run() {
        System.out.println("电梯运行了");
        context.setLiftState(Context.runningState);
    }

    @Override
    public void stop() {
        System.out.println("电梯停止中");
        context.setLiftState(Context.stoppingState);
    }
}

public class OpenningState extends LiftState{
    @Override
    public void open() {
        System.out.println("门开了");
    }

    @Override
    public void close() {
        System.out.println("门关上了");
        super.context.setLiftState(Context.closeingState);
    }

    @Override
    public void run() {

    }

    @Override
    public void stop() {

    }
}

测试 

public class Client {
    public static void main(String[] args) {
Context context = new Context();
        RunningState runningState = new RunningState();
        context.setLiftState(runningState);
        context.open();
        context.close();
        context.run();
        context.stop();
        System.out.println("=================");
        OpenningState openningState = new OpenningState();
        context.setLiftState(openningState);
        context.open();
        context.close();
        context.run();
        context.stop();
        System.out.println("=================");
        ClosingState closingState = new ClosingState();
        context.setLiftState(closingState);
        context.close();
        context.run();
        context.stop();
    }
}

电梯停了

=================

门开了

门关上了

电梯运行了

电梯停了

=================

电梯运行了

电梯停了

环境类与状态类互相聚合,通过环境类调用对应的状态方法。如果要更改状态需要当前具体状态角色的重写方法内调用环境的setLiftSate()方法。

盲点

环境类中的setLiftState()方法中为什么要进行setContext()方法,解释如注释,在一个新的状态相当于创建了个新的对象,新创建的对象环境属性的值自然为null,那么在客户端调用方法时,一定会报空指针异常。

优点

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

缺点

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

使用场景

  • 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。
  • 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时。

为什么要使用状态模式

正常情况下,如果要实现不同状态下要走不同的功能,要么使用switch-case语句或是if-else语句来实现,比如案例如果使用switch-case来实现的话,四种状态下就需要写四次switch-case来区分每次执行方法。并且如果新增其他状态,需要更改的地方过多且杂乱,因此使用状态模式更好些,不过对程序员代码能力要一定要求。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java如何获取调用接口的ip?

获取调用者的ip 场景:想知道哪个ip访问的某个接口时,就需要打印出来看看,这时就可以使用这个方法了。 案例: //HttpServletRequest 入参加上,请求对象public ForkResponse queryXXX(RequestBody XXXX xxxx, HttpServletRequest …

Zynq-Linux移植学习笔记之64- 国产ZYNQ在linux下配置国产5396芯片

1、背景介绍 复旦微ZYNQ通过SPI配置国产JEM5396,框图如下: 现在需要在linux下的应用程序内配置JEM5396的寄存器。其中FMQL和进口的XILINX ZYNQ类似,JEM5396和进口的BCM5396兼容。因此可以参考进口ZYNQ在linux下配置BCM5396过程。Zynq-Linux移…

驾驶技巧_新手

人人都是老司机 1> 快速起步(手动挡)2> 窄路会车3> 转弯4> 变道 1> 快速起步(手动挡) 【B站】视频讲解 Step 1> 【快 停 慢放】左脚离合,快速抬到半联动点; Step 2> 离合器慢放同时加油! 2> 窄路会车 3> 转弯 4&…

C++学习初探---‘C++面向对象‘-继承函数重载与运算符重载

文章目录 前言继承继承是什么?三种访问权限的继承: 函数重载与运算符重载函数重载运算符重载可重载运算符&不可重载运算符 前言 第三次学习记录,依旧是C面向对象的内容。 继承 继承是什么? C中的继承是一种面向对象编程&am…

Kubuntu安装教程

目录 1.介绍 2.安装 3.配置 更新软件 中文输入法 美化 1.介绍 Kubuntu,是众多Ubuntu分支的一种,它采用KDE Plasma桌面为其默认桌面环境。它和Ubuntu采用同样的底层系统和软件库。基本上,Kubuntu和Ubuntu没有太大的差异,只是…

Spring Boot 3系列之一(初始化项目)

近期,JDK 21正式发布,而Spring Boot 3也推出已有一段时间。作为这两大技术领域的新一代标杆,它们带来了许多令人振奋的新功能和改进。尽管已有不少博客和文章对此进行了介绍,但对于我们这些身处一线的开发人员来说,有些…

【Truffle】二、自定义合约测试

一、准备测试 上期我们自己安装部署了truffle,并且体验了测试用例的整个测试流程,实际开发中,我们可以对自己的合约进行测试。 我们首先先明白自定义合约测试需要几个文件 合约文件:既然要测试合约,肯定要有合约的源码…

[EFI]asus strix b760-i 13900F电脑 Hackintosh 黑苹果efi引导文件

硬件型号驱动情况主板 asus strix b760-i 处理器 I9 13900F 已驱动内存crucial ddr5-5200 64gb(32gb*2)(overclock 5600)已驱动硬盘 WD black sn850 500g*2 已驱动显卡rx570已驱动声卡Realtek ALCS1220A已驱动网卡Intel I225-V 2.5 Gigabit Ethernet已驱动无线网卡蓝牙Fevi T91…

通过内网穿透快速搭建公网可访问的Spring Boot接口调试环境

文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…

Spring Cloud Alibaba 之 Sentinel

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 第七章 Spring Cloud 之 GateWay 第八章 Sprin…

C++学习笔记之四(标准库、标准模板库、vector类)

C 1、C标准库2、C标准模板库2.1、vector2.1.1、vector与array2.1.2、vector与函数对象2.1.3、vector与迭代器2.1.4、vector与算法 1、C标准库 C C C标准库指的是标准程序库( S t a n d a r d Standard Standard L i b a r a y Libaray Libaray),它定义了十个大类…

x3daudio1 7.dll丢失怎么修复?多种x3daudio1 7.dll修复方法对比

x3daudio1_7.dll是Windows操作系统中的一个动态链接库文件,它主要负责处理音频相关的功能。当这个文件缺失或损坏时,可能会导致一些音频播放问题,如无声、杂音等。那么,x3daudio1_7.dll缺失的原因是什么呢?又该如何修复…

Unity 粒子特效-第五集-烟雾缭绕合并特效

一、特效预览 二、制作原理 1.素材介绍 我们之前几章做了有光球,星星,烟雾 我们把他们结合起来,做一些调整 2.合并方法 我们还是建一个粒子游戏物体 我们把所有的效果取消 再重置一下transform 现在这个物体就是一个可以控制粒子特效的空…

钢琴培训答题服务预约小程序的效果怎样

很多家长都会从小培养孩子的兴趣,钢琴便是其中热度较高的一种,而各城市也不乏线下教育培训机构,除了青少年也有成年人参加培训,市场教育高需求下,需要商家不断拓展客户和转化。 那么通过【雨科】平台制作钢琴培训服务…

【LeetCode力扣】42. 接雨水

目录 1、题目介绍 2、解题思路 2.1、暴力破解法 2.2、双指针法 1、题目介绍 原题链接: 42. 接雨水 - 力扣(LeetCode) 示例 1: 输入:height [0,1,0,2,1,0,1,3,2,1,2,1]输出:6解释:上面是由…

七、W5100S/W5500+RP2040树莓派Pico<UDP 组播>

文章目录 1. 前言2. 相关简介2.1 简述2.2 优点2.3 应用 3. WIZnet以太网芯片4. UDP 组播回环测试4.1 程序流程图4.2 测试准备4.3 连接方式4.4 相关代码4.5 测试现象 5. 注意事项6. 相关链接 1. 前言 UDP组播是一种基于UDP协议的通信方式,它允许一台计算机通过发送单…

HEC-RAS 1D/2D水动力与水环境模拟技术

水动力与水环境模型的数值模拟是实现水资源规划、环境影响分析、防洪规划以及未来气候变化下预测和分析的主要手段。然而,一方面水动力和水环境模型的使用非常复杂,理论繁复;另一方面,免费的水动力和水环境软件往往缺少重要功能&a…

rcore 笔记 第一个裸机程序

文章目录 环境应用程序与基本执行环境应用程序执行环境与基本操作平台执行应用程序应用程序执行环境目标平台与目标三元组 移除标准库依赖移除 println! 宏提供 panic_handler 功能应对致命错误移除 main 函数 编译运行内核指令程序内存布局与编译流程 内核第一条指令编写内核第…

计算机毕业设计选题推荐-短文写作竞赛微信小程序/安卓APP-项目实战

✨作者主页:IT毕设梦工厂✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

操作系统的内存管理之虚拟空间

操作系统的内存管理,主要分为三个方面。 第一,物理内存的管理,相当于会议室管理员管理会议室。 第二,虚拟地址的管理,也即在项目组的视角,会议室的虚拟地址应该如何组织。 第三,虚拟地址和物…
最新文章