设计模式示例_状态设计模式示例

设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。

在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 !

目录

1.简介 2.什么是状态设计模式 3.实施状态设计模式 4.何时使用状态设计模式 5. Java中的状态设计模式 6.下载源代码

1.简介

为了说明“状态设计模式”的使用,让我们帮助一家正在寻求制造烹饪机器人的公司。 该公司想要一个简单的机器人,它可以简单地走路和煮饭。 用户可以通过遥控器使用一组命令来操作机器人。 当前,机器人可以做三件事,它可以走路,做饭或关闭。

该公司已设置协议来定义机器人的功能。 如果机器人处于“打开”状态,则可以命令它行走。 如果要求烹饪,状态将变为“烹饪”,或者如果设置为“关闭”,则将其关闭。

同样,处于“烹饪”状态时,它可以走路或做饭,但不能关闭。 最后,当处于“关闭”状态时,当用户命令它走路但不能在关闭状态下烹饪时,它将自动上走。

这看起来像是一个简单的实现:机器人类具有一组方法,例如步行,烹饪,关闭以及状态(例如打开,烹饪和关闭)。 我们可以使用if-else分支或使用switch来实施公司设置的协议。 但是过多的if-else或switch语句将造成维护的噩梦,因为将来的复杂性可能会增加。

您可能认为我们可以使用if-else语句来实现此目的,但是随着更改的来临,代码将变得更加复杂。 需求清楚地表明,对象的行为确实基于该对象的状态。 我们可以使用状态设计模式,该模式将对象的状态封装到另一个单独的类中,并使上下文类独立于任何状态更改。

首先让我们了解状态设计模式,然后将其实现以解决上述问题。

2.什么是状态设计模式

状态设计模式允许对象在其内部状态更改时更改其行为。 该对象似乎将更改其类。

可以将对象的状态定义为在任何给定时间点的确切条件,具体取决于其属性或属性的值。 由类实现的方法集构成其实例的行为。 只要它的属性值发生变化,我们就说对象的状态发生了变化。

状态模式可用于为类设计有效的结构,该类的典型实例可以存在于许多不同的状态中,并根据其所处的状态而表现出不同的行为。换句话说,对于此类对象,类,其某些或全部行为完全受其当前状态影响。 在状态设计模式术语中,此类称为Context类。 当内部状态发生变化时, Context对象可以更改其行为,也称为有状态对象。

State模式建议将特定于状态的行为从Context类中移出,称为一组单独的类,称为State类。 Context对象可以存在的许多不同状态中的每一个都可以映射到单独的State类中。 State类的实现包含特定于给定状态的上下文行为,而不是上下文本身的整体行为。 从某种意义上说,上下文是状态对象集的客户端,它利用不同的状态对象为无缝使用上下文的应用程序对象提供必要的特定于状态的行为。

通过将特定于状态的行为封装在单独的类中,上下文实现变得更易于阅读:无需太多条件语句(例如if-else或switch-case构造)。 首次创建Context对象时,它将使用其初始State对象进行初始化。 该State对象成为上下文的当前State对象。 通过用新的State对象替换当前的State对象,上下文将转换为新的状态。

使用上下文的客户端应用程序不负责为上下文指定当前的State对象,而是代表特定状态的每个State类均应提供将上下文转换为其他状态的必要实现。 当应用程序对象调用Context方法(行为)时,它将方法调用转发到其当前的State对象。

图1-类图

图1 –类图

语境

  • 定义客户感兴趣的接口。
  • 维护定义当前状态的ConcreteState子类的实例。

  • 定义一个接口,用于封装与上下文的特定状态关联的行为。

ConcreteState子类

  • 每个子类都实现与Context状态关联的行为。

3.实施状态设计模式

以下是RoboticState接口,其中包含机器人的行为。

package com.javacodegeeks.patterns.statepattern;public interface RoboticState {public void walk();public void cook();public void off();}

Robot类是实现RoboticState接口的具体类。 该类包含机器人可能处于的所有可能状态的集合。

package com.javacodegeeks.patterns.statepattern;public class Robot implements RoboticState{private RoboticState roboticOn;private RoboticState roboticCook;private RoboticState roboticOff;private RoboticState state;public Robot(){this.roboticOn = new RoboticOn(this);this.roboticCook = new RoboticCook(this);this.roboticOff = new RoboticOff(this);this.state = roboticOn;}public void setRoboticState(RoboticState state){this.state = state;}@Overridepublic void walk() {state.walk();}@Overridepublic void cook() {state.cook();}@Overridepublic void off() {state.off();}public RoboticState getRoboticOn() {return roboticOn;}public void setRoboticOn(RoboticState roboticOn) {this.roboticOn = roboticOn;}public RoboticState getRoboticCook() {return roboticCook;}public void setRoboticCook(RoboticState roboticCook) {this.roboticCook = roboticCook;}public RoboticState getRoboticOff() {return roboticOff;}public void setRoboticOff(RoboticState roboticOff) {this.roboticOff = roboticOff;}public RoboticState getState() {return state;}public void setState(RoboticState state) {this.state = state;}}

该类初始化所有状态并将当前状态设置为on。

现在,我们将看到机器人的所有具体状态。 机器人将随时处于任何一种状态。

package com.javacodegeeks.patterns.statepattern;public class RoboticOn implements RoboticState{private final Robot robot;public RoboticOn(Robot robot){this.robot = robot;}@Overridepublic void walk() {System.out.println("Walking...");}@Overridepublic void cook() {System.out.println("Cooking...");robot.setRoboticState(robot.getRoboticCook());}@Overridepublic void off() {robot.setState(robot.getRoboticOff());System.out.println("Robot is switched off");}}
package com.javacodegeeks.patterns.statepattern;public class RoboticCook implements RoboticState{private final Robot robot;public RoboticCook(Robot robot){this.robot = robot;}@Overridepublic void walk() {System.out.println("Walking...");robot.setRoboticState(robot.getRoboticOn());}@Overridepublic void cook() {System.out.println("Cooking...");}@Overridepublic void off() {System.out.println("Cannot switched off while cooking...");}
}
package com.javacodegeeks.patterns.statepattern;public class RoboticOff implements RoboticState{private final Robot robot;public RoboticOff(Robot robot){this.robot = robot;}@Overridepublic void walk() {System.out.println("Walking...");robot.setRoboticState(robot.getRoboticOn());}@Overridepublic void cook() {System.out.println("Cannot cook at Off state.");}@Overridepublic void off() {System.out.println("Already switched off...");}
}

现在,让我们测试代码。

package com.javacodegeeks.patterns.statepattern;public class TestStatePattern {public static void main(String[] args) {Robot robot = new Robot();robot.walk();robot.cook();robot.walk();robot.off();robot.walk();robot.off();robot.cook();}}

上面的代码将导致以下输出:

Walking...
Cooking...
Walking...
Robot is switched off
Walking...
Robot is switched off
Cannot cook at Off state.

在上面的示例中,我们已经看到通过将对象的状态封装到不同的类中可以使代码易于管理和灵活。

状态的任何更改只会影响该特定类,并且我们可以包括一个新状态而无需在现有代码中进行太多更改。 例如,我们包含一个备用状态。 散步或做饭后,机器人会进入待机模式以节省电量,然后我们再次步行,做饭或从待机模式下关闭。

为了实现所有这些,我们需要引入一个新的状态类,并将该状态包括在Robot类中。 以下是更改。

package com.javacodegeeks.patterns.statepattern;public class Robot implements RoboticState{private RoboticState roboticOn;private RoboticState roboticCook;private RoboticState roboticOff;private RoboticState roboticStandby;private RoboticState state;public Robot(){this.roboticOn = new RoboticOn(this);this.roboticCook = new RoboticCook(this);this.roboticOff = new RoboticOff(this);this.roboticStandby = new RoboticStandby(this);this.state = roboticOn;}public void setRoboticState(RoboticState state){this.state = state;}@Overridepublic void walk() {state.walk();setState(getRoboticStandby());}@Overridepublic void cook() {state.cook();setState(getRoboticStandby());}@Overridepublic void off() {state.off();}public RoboticState getRoboticOn() {return roboticOn;}public void setRoboticOn(RoboticState roboticOn) {this.roboticOn = roboticOn;}public RoboticState getRoboticCook() {return roboticCook;}public void setRoboticCook(RoboticState roboticCook) {this.roboticCook = roboticCook;}public RoboticState getRoboticOff() {return roboticOff;}public void setRoboticOff(RoboticState roboticOff) {this.roboticOff = roboticOff;}public RoboticState getState() {return state;}public void setState(RoboticState state) {this.state = state;}public RoboticState getRoboticStandby() {return roboticStandby;}public void setRoboticStandby(RoboticState roboticStandby) {this.roboticStandby = roboticStandby;}}
package com.javacodegeeks.patterns.statepattern;public class RoboticStandby implements RoboticState{private final Robot robot;public RoboticStandby(Robot robot){this.robot = robot;}@Overridepublic void walk() {System.out.println("In standby state...");robot.setState(robot.getRoboticOn());System.out.println("Walking...");}@Overridepublic void cook() {System.out.println("In standby state...");robot.setRoboticState(robot.getRoboticCook());System.out.println("Cooking...");}@Overridepublic void off() {System.out.println("In standby state...");robot.setState(robot.getRoboticOff());System.out.println("Robot is switched off");}}

现在,以上代码更改将导致以下输出:

Walking...
In standby state...
Cooking...
In standby state...
Walking...
In standby state...
Robot is switched off
Walking...
In standby state...
Robot is switched off
Cannot cook at Off state.

4.何时使用状态设计模式

在以下两种情况下,请使用State模式:

  • 对象的行为取决于其状态,并且它必须在运行时根据该状态更改其行为。
  • 操作具有取决于对象状态的大型,多部分条件语句。 此状态通常由一个或多个枚举常量表示。 通常,几个操作将包含此相同的条件结构。 State模式将条件的每个分支放在单独的类中。 这样,您就可以将对象的状态视为独立于其他对象而独立变化的对象。

5. Java中的状态设计模式

  • javax.faces.lifecycle.LifeCycle#execute()

6.下载源代码

这是关于状态设计模式的课程。 您可以在此处下载源代码: StatePattern-Project

翻译自: https://www.javacodegeeks.com/2015/09/state-design-pattern.html

设计模式示例

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

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

相关文章

cam350 不能打开光绘文件_如何在CAM350中导入Allegro光绘

内容简介:本人之前遇到过 CAM350 导入 Allegro 格式光绘后钻孔偏移、异型孔不显示的问题,捣鼓过之后找到一个方法,在 Allegro 群友的建议下制作该文档进行适当的说明。1. 导入 Gerber 文件鉴于手工导入 Gerber 文件需要逐层设置,过…

d3js mysql_D3.js入门指南

近期略有点诸事不顺,趁略有闲余之时,玩起D3.js。之前实际项目中主要是用各种chart如hightchart、echarts等,这些图形库玩起来貌都是完美的,一切皆可配置,但几年前接触了D3之后,觉得前面那chart类库局限的地…

layui templet格式化_layui使用templet格式化表格数据的方法

增加js/*---------------------格式化时间开始--------------------------*///对Date的扩展,将 Date 转化为指定格式的String//月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,//年(y)可以用 1-4 个占位符,毫秒(S)只能用…

设计模式示例_代理设计模式示例

设计模式示例本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 &#x…

mysql insert 字符集_有关 MySQL 字符集的注意事项-爱可生

本文关键字:字符集、建库建表一、数据库和字符集1. 建库时指定创建数据库时,显式指定字符集和排序规则,同时,当切换到当前数据库后,参数 character_set_database,collation_database 分别被覆盖为当前显式指…

c#发送讯息_企业讯息

c#发送讯息本文是我们名为“ EAI的Spring集成 ”的学院课程的一部分。 在本课程中,向您介绍了企业应用程序集成模式以及Spring Integration如何解决它们。 接下来,您将深入研究Spring Integration的基础知识,例如通道,转换器和适…

java cr_WildFly 10 CR 2发布– Java EE 7,Java 8,Hibernate 5,JavaScript支持热重载

java cr昨天,WildFly团队发布了最新版本的WildFly 10 。 CR2很可能是预计于十月份发布最终版本之前的最后一个版本。 即使主要支持的Java EE规范是7,WildFly 8和WildFly 9也提供了许多新功能,而WildFly 9和WildFly 9现在制作了三个服务器版本…

侬娜·杰尔_杰尔·地狱

侬娜杰尔什么是JAR地狱? (或者是classpath地狱?还是依赖地狱?)在考虑使用Maven或OSGi等现代开发工具时,哪些方面仍然有意义? 有趣的是,似乎没有对这些问题的结构化答案(…

Mysql运行在内核空间_思考mysql内核之初级系列6—innodb文件管理 | 学步园

在上一篇里面,bingxi和alex思考了information_schema,这个一直在innodb外围打转。没有进入到innodb的内部。在后续的文章中,以innodb的为主,逐个思考。Bingxi和alex今天了解了fil文件管理。对应的文件为:D:/mysql-5.1.…

pcl_openmap_OpenMap教程第2部分–使用MapHandler构建基本地图应用程序–第1部分

pcl_openmap1.简介 在第一个教程中,我们创建了一个基本的OpenMap GIS应用程序,该应用程序在JFrame中显示一个从文件系统加载的具有一个形状图层的地图。 该教程基于com.bbn.openmap.app.example.SimpleMap 。 在该教程中,我们使用了以下OpenM…

mysql7.5安装教程_CentOS7.5下yum安装MySQL8图文教程

卸载MariaDB1.列出所有安装的MariaDB rpm 包rpm -qa | grep mariadb2.强制卸载rpm -e --nodeps mariadb-libs-5.5.60-1.el7_5.x86_64安装MySQL1. 环境CentOS7.52. 获取MySQL最新版 rpm包yum仓库下载MySQLyum localinstall https://repo.mysql.com//mysql80-community-release-e…

mysql和sqlserver分页的区别_关于SQLServer和MySQL 查询分页语句区别

首先来定义几个要用到的参数(例子)t_user数据表int currentPage ; //当前页int pageRecord ; //每页显示记录数关于SqlServer数据库分页SQL语句为:String sql "select top "pageRecord " * from t_user where id not in (select top "(currentPage-1)*pag…

java 微型数据库_Java 9代码工具:使用Java微型基准测试工具的实践会话

java 微型数据库用肉眼看,基准测试似乎只是确定执行某些代码需要花费多长时间的简单问题。 但是,通常情况下,这是幼稚的方法。 提供具有准确和可重复结果的有意义的基准并非易事。 在本文中,我们将向您介绍OpenJDK代码工具项目&a…

mysql快速随机_MySQL随机取数据最高效的方法

mysql随机取数据最高效率的方法发现在SQL语句里有一个 ORDER BY rand() 这样的一个语句,这个说是用着方便,但是效率实在是太低了,于是我用了以下的方法来优化,就是用JOIN表的方法来达到这个取随机数据行的方法,你可以用…

部署被测软件应用和中间件_使用FlexDeploy对融合中间件应用程序进行自动化软件测试...

部署被测软件应用和中间件自动化软件测试是任何软件组织都必须执行的强制性活动之一,以保证其产品质量。 但是,此过程通常变得相当复杂,尤其是涉及由多个不同部分组成的现代复杂系统的自动化测试时。 所有这些部分都基于不同的技术&#xff0…

投行数据_投行对Java的二十大核心访谈问答

投行数据这是在金融领域(主要是在大型投资银行)共享Java核心访谈问题和答案的新系列。 在JP Morgan,Morgan Stanley,Barclays或Goldman Sachs上会问许多这些Java面试问题。 银行主要从多线程 , 集合 ,序列化…

primefaces_通过OmniFaces缓存组件以编程方式缓存PrimeFaces图表

primefaces在这篇文章中&#xff0c;您将看到如何结合PrimeFaces和OmniFaces获得可缓存的图表。 为了使事情变得简单&#xff0c;我们将使用PrimeFaces 折线图。 对于这种图表&#xff0c;我们可以在页面中使用<p&#xff1a;chart />标签和一个简单的托管bean。 因此&am…

hmailserver mysql密码_第二步:点晴MIS系统Email模块hMailServer数据库连接配置指引

点击&#xff1a;windows系统-》开始-》所有程序-》hmailserver-》hMailServer Database Setup&#xff0c;在弹出的对话框中输入默认管理密码“clicksun2010”&#xff0c;进入后按照以下步骤操作&#xff1a;输入登陆密码&#xff1a;clicksun2010&#xff0c;务必使用这个密…

spring3.0异步_在Spring 4.2中更简单地处理异步事务绑定事件

spring3.0异步介绍 如您可能已经知道的&#xff08;例如&#xff0c;从我以前的博客文章中 &#xff09;&#xff0c;不再需要创建一个单独的类来实现带有onApplicationEvent方法的ApplicationListener &#xff0c;以便能够对应用程序事件做出响应&#xff08;包括来自Spring …

java实现ldap服务器_Java到LDAP教程(包括如何安装LDAP服务器/客户端)

java实现ldap服务器本教程将向您展示如何编写Java代码以与LDAP交互。 但是在执行此操作之前&#xff0c;我们需要在计算机上设置LDAP服务器和客户端。 如果此时您不确定到底是什么LDAP&#xff0c;建议您使用这篇文章&#xff0c;其中提供了一个很好的定义示例。 &#xff08;…