热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

状态模式(二十二)

一、定义当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。怎么理解这句话呢,就比方水有不同的状态,气体、液体和固体&#x

一、定义

    当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
    怎么理解这句话呢,就比方水有不同的状态,气体、液体和固体,不同的状态拥有的行为和特征也不一致,例如水可以用来洗衣服,冰可以冷藏东西,水蒸气有遇冷会液化的行为,它们还是同一个对象,但是在不同的状态看起来像改变了其类。


二、角色

1. State 抽象状态角色

    接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换。

public abstract class State {//定义一个环境角色, 提供子类访问protected Context context;//设置环境角色public void setContext(Context _context){this.context = _context;}//行为1public abstract void handle1();//行为2public abstract void handle2();
}

2. ConcreteState 具体状态角色

    每一个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理,通俗地说,就是本状态下要做的事情,以及本状态如何过渡到其他状态。

public class ConcreteState1 extends State {@Overridepublic void handle1() {//本状态下必须处理的逻辑}@Overridepublic void handle2() {//设置当前状态为stat2super.context.setCurrentState(Context.STATE2);//过渡到state2状态, 由Context实现super.context.handle2();}
}public class ConcreteState2 extends State {@Overridepublic void handle1() {//设置当前状态为state1super.context.setCurrentState(Context.STATE1);//过渡到state1状态, 由Context实现super.context.handle1();}@Overridepublic void handle2() {//本状态下必须处理的逻辑}
}

3. Context 环境角色

    定义客户端需要的接口,并且负责具体状态的切换。

public class Context {//定义状态public final static State STATE1 = new ConcreteState1();public final static State STATE2 = new ConcreteState2();//当前状态private State currentState;//获得当前状态public State getCurrentState() {return currentState;}//设置当前状态public void setCurrentState(State currentState) {this.currentState = currentState;//切换状态this.currentState.setContext(this);}//行为委托public void handle1() {this.currentState.handle1();}public void handle2() {this.currentState.handle2();}
}

环境角色有两个不成文的规定,即:

  1. 把状态对象声明为静态常量,有几个状态对象就声明几个静态常量。
  2. 环境角色具有状态抽象角色定义的所有行为,具体执行使用委托方式。

4. 场景模拟

public class Client {public static void main(String[] args) {//定义环境角色Context context = new Context();//初始化状态context.setCurrentState(new ConcreteState1());//行为执行context.handle1(); //执行State1的handle1context.handle2(); //执行State2的handle2}
}

三、优缺点

  • 优点:
  1. 结构清晰
    如果不是有状态模式,一个对象需要在不同状态执行不同方法或者拥有不同特性的话,你可能需要在大量的 switch...case 或者 if...else 语句来根据不同状态执行不同方法,代码看起来就很复杂了
  2. 遵循设计原则
    每一个状态都是一个子类,符合单一职责原则,且当需要增加一个状态时,也是可以增加一个子类,需要修改一个状态时,也是修改一个子类即可。
  3. 封装性好
    状态的变换放置在类的内部实现,外部调用就不需要知道类的内部是如何实现状态和行为的变换了。
  • 缺点:
  1. 子类多
    每一个状态都对应一个子类,如果完全使用状态模式就会有太多的子类,不好管理,需要在项目中权衡。
    为了避免子类过多,也可以在数据库中建立一个状态表,然后根据状态执行相应操作,也不会太复杂。


四、使用场景

  1. 对象的行为会随状态改变而改变
  2. 条件、分支判断语句的替代者


查看更多:设计模式分类以及六大设计原则



推荐阅读
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
author-avatar
我无眼泪1221
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有