【设计模式】状态模式

文章目录

  • 引例
  • 状态模式理论
  • 状态模式代码优化
    • 结合享元模式
    • 并发问题解决
  • 策略模式 VS 状态模式

引例

交通信号灯系统的设计与实现
image.png
方案一
传统设计方案
定义交通灯颜色的枚举```

public enum LightColor {
Green,Red,Yellow
}

交通灯类TrafficLight,处理颜色转换等业务逻辑

public class TrafficLight{private LightColor lightColor;// 将信号灯初始化为红灯public TrafficLight(){lightColor = LightColor.Red;}// 信号转换处理public void changeSignal(){if (lightColor == LightColor.Red){System.out.println("红灯停");lightColor = LightColor.Green;}else if (lightColor == LightColor.Green){System.out.println("绿灯行");lightColor = LightColor.Yellow;}else if (lightColor == LightColor.Yellow){System.out.println("黄灯亮了等一等");lightColor = LightColor.Red;}}
}

客户端类

public class Client{public static void main(String[] args){TrafficLight light = new TrafficLight();light.changeSignal();light.changeSignal();light.changeSignal();}
}

运行结果为:

红灯停
绿灯行
黄灯亮了等一等

说明:

  1. TrafficLight类种的if-else条件分支违背开闭原则

方案二
参考策略模式进行修改
image.png
说明:

  1. 将交通灯的展示即display()做成了策略,因而策略类形成了层次类,满足OCP
  2. 具体类满足单一职责
  3. 环境类引用策略完成展示和交通灯颜色切换

代码说明
交通灯层次类

public interface ITrafficLightStrategy {void display();
}public class RedLightStrategy implements ITrafficLightStrategy {@Overridepublic void display() {System.out.println("红灯停");}
}public class GreenLightStrategy implements ITrafficLightStrategy {@Overridepublic void display() {System.out.println("绿灯行");}
}public class YellowLightStrategy implements ITrafficLightStrategy {@Overridepublic void display() {System.out.println("黄灯请等一等");}
}

环境类Context:
在Context类中有一个ITrafficLightStrategy对象,用于控制当前的交通灯颜色,showSignal()方法显示,changeSignalStrategy()方法改变交通灯

public class Context {private ITrafficLightStrategy trafficLightStrategy;public TrafficLight(ITrafficLightStrategy trafficLightStrategy) {this.signalStrategy = signalStrategy;}public void showSignal() {if (signalStrategy != null) {            signalStrategy.displaySignal();}}public void changeSignalStrategy (ITrafficLightStrategy trafficLightStrategy) {this.signalStrategy = signalStrategy;}
}

Client类实现:

public class Client {public static void main(String[] args) {Context context = new Context(new RedLightStrategy());    context.showSignal();context.changeSignalStrategy(new GreenLightStrategy());context.showSignal();context.changeSignalStrategy(new YellowLightStrategy());context.showSignal();}
}

说明:在方案二的设计中交通灯的颜色切换实现是完全暴露给Client的,不符合面向对象的封装特性

方案三
将每种颜色的灯做成一个类,但又不能是像工厂方法模式那样的创建型模式,因为三个灯从始至终都是没有改变的。
这里我们考虑把每种颜色的灯表达为一种状态
image.png
仔细看方案三和方案二的类图差别
在方案三的State.display(Context)方法中有一个Context对象作为参数传递,这表示的是在display()方法中利用Context改变当前交通灯的状态。另外,这也带来了Context类和ITrafficLightState层次类的双向依赖
交通灯的状态切换具体而言是在display()方法中加入以下语句:

//在具体的状态子类中告诉环境对象Context,下一个状态是谁。
context.changeCurrentSignal(new RedLightState());

交通灯接口设计:

public interface ITrafficLightState {
void display(Context context); // 反向关联到Context,取得系统的上下文环境
}

Context类的设计:相比于方案二,changeSignal()方法中具体切换代码从Client类移动到了State类的display()方法中

public class Context {private ITrafficLightState currentState;public Context() {this.currentState = new RedLightState();}public void showSignal() {if (currentState != null) {currentState.display(this); // this表示当前context对象}}public void changeCurrentSignal(ITrafficLightState currentState) {this.currentState = currentState;}
}

Client类的设计:

public class Client {public static void main(String[] args) {Context context = new Context();context.showSignal();context.showSignal();context.showSignal();}
}

状态模式理论

定义:允许状态对象在其内部状态发生改变时改变其行为,通过将抽象有状态的对象,将复杂的状态改变“判断逻辑”提取到不同状态对象中实现
image.png
优点

  1. 解决switch-case、if-else带来的难以维护的问题
  2. 代码结构清晰,提高了扩展性

缺点

  1. 状态扩展导致状态类数量增多
  2. 增加了系统复杂度,使用不当将会导致逻辑的混乱
  3. 不完全满足开闭原则,增加或者删除状态类时,需要修改涉及到的状态转移逻辑和对应的类

应用场景
一个操作的判断逻辑/行为取决于对象的内部状态时

状态模式代码优化

结合享元模式

对象重复创建问题
每次状态切换都需要创建一个新的状态对象,而事实上一个状态对象完全可以只用一个枚举值标识,这带来巨大的额外资源开销。
解决方法
单例模式
享元模式

享元模式代码示例:新增一个Factory创建状态对象的工厂类,在这个Factory类中维护着一个现有的ITrafficLightState状态层次类Map,State类在需要new状态对象时,调用Factory的getTrafficLight方法,如果维护的map中有该类对象,则直接返回;如果没有,则创建一个新的状态对象返回。由此来减少状态模式中的对象重复创建

public class TrafficLightStateFactory {  //享元模式// 共享Mapprivate static Map<Class, ITrafficLightState> lights = new HashMap();public static ITrafficLightState getTrafficLight(Class key) {if(!(lights.containsKey(key))) {try {lights.put(key, (ITrafficLightState) key.getDeclaredConstructor().newInstance());} catch (Exception e) {throw new RuntimeException(e);}}return lights.get(key);}
}

ConcreteState类的对应修改

public class GreenLightState implements ITrafficLightState {@Overridepublic void display(Context context) throws Exception {System.out.println("绿灯行");context.changeCurrentSignal(TrafficLightStateFactory.getTrafficLight(YellowLightState.class));}
}

并发问题解决

由于状态是单例的,可以在多个上下文之间共享。若状态类中持有其他资源就有产生并发问题的可能
于是,我们可以看在前面的方案三设计中,State层次类中对Context类的依赖是来自display()方法的参数,而没有通过属性的方法持有Context对象的引用

策略模式 VS 状态模式

image.png
说明:策略模式持有Context对象一般是需要使用context对象中的数据或方法,如H5所述的使用Context对象的计时方法。

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

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

相关文章

安全配置审计概念、应用场景、常用基线及扫描工具

软件安装完成后都会有默认的配置&#xff0c;但默认配置仅保证了服务正常运行&#xff0c;却很少考虑到安全防护问题&#xff0c;攻击者往往利用这些默认配置产生的脆弱点发起攻击。虽然安全人员已经意识到正确配置软件的重要性&#xff0c;但面对复杂的业务系统和网络结构、网…

【数学建模美赛M奖速成系列】Matplotlib绘图技巧(一)

Matplotlib图像基础 写在前面1 基本绘图实例&#xff1a;sin、cos函数图2 plot()函数详解**kwargs参数&#xff1a; 3 matplotlib中绘图的默认配置4 设置图的横纵坐标的上下界5 设置横纵坐标上的记号6 调整图像的脊柱7 添加图例8 给一些特殊点加注释9 子图最后 写在前面 前面我…

CentOS7安装部署Zookeeper

文章目录 CentOS7安装部署Zookeeper一、前言1.简介2.架构3.集群角色4.特点5.环境 二、正文1.部署服务器2.基础环境1&#xff09;主机名2&#xff09;Hosts文件3&#xff09;关闭防火墙4&#xff09;JDK 安装部署 3.单机部署1&#xff09;下载和解压2&#xff09;配置文件3&…

第一讲:BeanFactory和ApplicationContext

BeanFactory和ApplicationContext 什么是BeanFactory 它是ApplicationContext的父接口它才是Spring的核心容器&#xff0c;主要的ApplicationContext实现都组合了它的功能 BeanFactory能做什么? 表面上看BeanFactory的主要方法只有getBean()&#xff0c;实际上控制反转、基…

路由器IP地址及直连实验

实验目的&#xff1a; &#xff08;1&#xff09;理解IP地址&#xff1b; &#xff08;2&#xff09;掌握路由器端口IP地址的配置方法&#xff1b; &#xff08;3&#xff09;理解路由器的直连网络。 实验器材&#xff1a; Cisco packet 实验内容&#xff1a; 实验步骤&a…

【ArcGIS微课1000例】0083:地震灾害图件制作之土壤类型分布图

本文基于1:400万矢量土壤图,制作甘肃积石山6.2级地震100km范围内土壤类型分布图。 文章目录 一、土壤分布图预览二、数据集来源及简介三、土壤分布图制作一、土壤分布图预览 二、数据集来源及简介 1. 数据来源 数据集为1:400万中国土壤图,1:400万中国土壤图(2000)由中国科…

大创项目推荐 深度学习交通车辆流量分析 - 目标检测与跟踪 - python opencv

文章目录 0 前言1 课题背景2 实现效果3 DeepSORT车辆跟踪3.1 Deep SORT多目标跟踪算法3.2 算法流程 4 YOLOV5算法4.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; *…

模式识别与机器学习-集成学习

集成学习 集成学习思想过拟合与欠拟合判断方法 K折交叉验证BootstrapBagging随机森林的特点和工作原理&#xff1a; BoostingAdaBoost工作原理&#xff1a;AdaBoost的特点和优点&#xff1a;AdaBoost的缺点&#xff1a; Gradient Boosting工作原理&#xff1a;Gradient Boostin…

android 13.0 Launcher3长按app弹窗设置为圆角背景功能实现一

1.前言 在13.0的系统ROM定制化开发中,在进行一些Launcher3的定制化开发中,在使用app的弹窗的功能时,会弹出应用信息和微件之类的内容,所以在定制需求中,需要默认设置为圆角背景,接下来就来分析下相关功能的实现 如图: 2.Launcher3长按app弹窗设置为圆角背景功能实现的核…

【MYSQL】-函数

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

AcWing 1076. 迷宫问题(最短路模型)

题目链接 活动 - AcWing本课程系统讲解常用算法与数据结构的应用方式与技巧。https://www.acwing.com/problem/content/description/1078/ 来源 《信息学奥赛一本通》, kuangbin专题 , POJ3984 代码 #include <cstring> #include <iostream> #include <alg…

【网络安全常用术语解读】SCAP详解

本文主要介绍什么是SCAP&#xff0c;SCAP的产生背景是怎样的&#xff0c;SCAP有什么用途&#xff0c;有哪些组件&#xff0c;各个组件的用途是什么&#xff1f; SCAP产生背景 由于计算机和网络技术的快速发展&#xff0c;越来越多的软件和系统被应用到企业和机构中&#xff0c…

迭代归并:归并排序非递归实现解析

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《数据结构&算法》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! &#x1f4cb; 前言 归并排序的思想上我们已经全部介绍完了&#xff0c;但是同时也面临和快速排序一样的问题那就是递…

通信原理课设(gec6818) 007:语音识别

目录 1、去科大讯飞官网下载对应的sdk 2、科大讯飞文件夹的意思 3、配置ARM的录音环境 4、编程实现语音识别 我们的需求是将一个语音文件从客户端传到服务器&#xff0c;因此我们最好是选用tcp 现在市面上面常用的语音识别解决方案为&#xff1a;科大讯飞c和百度c 离…

龙芯3A5000上安装使用QQ

原文链接&#xff1a;龙芯3A5000上安装使用QQ hello&#xff0c;大家好啊&#xff01;今天我要给大家带来的是在龙芯3A5000处理器上安装使用QQ的文章。近期&#xff0c;腾讯发布了最新版本的QQ&#xff0c;值得一提的是&#xff0c;这一版本增加了对Linux系统下龙芯架构的支持。…

KG+LLM(一)KnowGPT: Black-Box Knowledge Injection for Large Language Models

论文链接&#xff1a;2023.12-https://arxiv.org/pdf/2312.06185.pdf 1.Background & Motivation 目前生成式的语言模型&#xff0c;如ChatGPT等在通用领域获得了巨大的成功&#xff0c;但在专业领域&#xff0c;由于缺乏相关事实性知识&#xff0c;LLM往往会产生不准确的…

项目记录:利用Redis实现缓存以提升查询效率

一、概述 当我们查询所有数据时&#xff0c;如果缓存中没有&#xff0c;则去数据库查询&#xff0c;如果有&#xff0c;直接查缓存的数据就行。注意定期更新缓存数据。 二、主体代码 private static final String ROOM_SCHEDULES_HASH "RoomSchedules";Overridepu…

HTML---JavaScript基础

文章目录 目录 文章目录 本章目标 一.JavaScript基础 概述 特点 JavaScript 基本机构 语法 网页中引用JavaScript的方式 二. JavaScript核心语法 变量 ​编辑 数据类型 数组 练习 本章目标 掌握JavaScript的组成掌握JavaScript的基本语法会定义和使用函数会使用工具进行…

引领手游技术潮流:武汉灰京文化的卓越技术创新与市场推广支持

在数字娱乐领域&#xff0c;手游行业正蓬勃发展&#xff0c;为数以亿计的玩家提供了丰富的娱乐选择。武汉灰京文化&#xff0c;作为该领域的佼佼者&#xff0c;以其强大的技术创新和全面的市场推广支持&#xff0c;为合作伙伴的成功铺平了道路&#xff0c;不仅提升了游戏质量&a…

TV端Web页面性能优化实践

01 背景 随着互联网技术的持续创新和电视行业的高速发展&#xff0c;通过电视观看在线视频已经逐渐成为大众的重要娱乐方式。奇异果App作为在TV设备上用户活跃度最高的应用之一&#xff0c;为广大用户提供了丰富的内容播放服务&#xff0c;除此之外&#xff0c;同样有会员运营、…