文章目录

  • 一、状态模式定义
  • 二、状态模式的结构和说明
  • 三、状态模式示例
  • 四、状态模式的优缺点
  • 五、状态模式的应用场景及案例

一、状态模式定义

Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.
(允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。)

二、状态模式的结构和说明

  • Context 环境,也称上下文。 定义客户端需要的接口,并且负责具体状态的切换。
  • State 状态接口。 负责状态行为方法的声明定义。
  • ConcreteState 具体实现状态处理的类。 实现State状态接口中声明的方法。

三、状态模式示例

  玩《王者农药》的同学都知道,王者中很多英雄是支持多形态的,以裴擒虎为例,裴擒虎在人形态和虎形态状态下,普通攻击以及各个技能效果都是不同的。
  我们通过代码来模拟一下。

不用状态模式的实现方式

定义裴擒虎类,类中记录当前所属形态,通过if-else区分不同形态进行不同的逻辑处理。

/*** 裴擒虎*/
public class Peiqianhu {/*** 定义裴擒虎形态枚举*/enum PeiqianhuShapeState{HUMAN, TIGER}/*** 裴擒虎当前形态*/private PeiqianhuShapeState peiqianhuShapeState;/*** 更换形态*/public void changeState(PeiqianhuShapeState peiqianhuShapeState){this.peiqianhuShapeState = peiqianhuShapeState;}/*** 普通攻击*/public void normalAttack() {if(Objects.equals(peiqianhuShapeState, PeiqianhuShapeState.HUMAN)){System.out.println("【人形态 - 普攻】远程气波攻击");}else if(Objects.equals(peiqianhuShapeState, PeiqianhuShapeState.TIGER)){System.out.println("【虎形态 - 普攻】近距离爪击攻击");}else{System.out.println("不支持的形态");}}/*** 释放一技能*/public void releaseFirstSkill() {if(Objects.equals(peiqianhuShapeState, PeiqianhuShapeState.HUMAN)){System.out.println("【人形态 - 一技能 - 冲拳式】朝指定方向发出气功波");}else if(Objects.equals(peiqianhuShapeState, PeiqianhuShapeState.TIGER)){System.out.println("【虎形态 - 一技能 - 虎啸式】对一名敌人发起撕咬");}else{System.out.println("不支持的形态");}}/*** 释放二技能*/public void releaseSecondSkill() {if(Objects.equals(peiqianhuShapeState, PeiqianhuShapeState.HUMAN)){System.out.println("【人形态 - 二技能 - 气守式】施展念气,产生护盾");}else if(Objects.equals(peiqianhuShapeState, PeiqianhuShapeState.TIGER)){System.out.println("【虎形态 - 二技能 - 虎跃式】朝指定方向冲刺");}else{System.out.println("不支持的形态");}}/*** 释放三技能*/public void releaseThirdSkill() {if(Objects.equals(peiqianhuShapeState, PeiqianhuShapeState.HUMAN)){System.out.println("【人形态 - 三技能 - 虎啸风生】变身为虎形态");// 变身为虎形态changeState(PeiqianhuShapeState.TIGER);}else if(Objects.equals(peiqianhuShapeState, PeiqianhuShapeState.TIGER)){System.out.println("【虎形态 - 三技能 - 形意六合】变身为人形态");// 变身为人形态changeState(PeiqianhuShapeState.HUMAN);}else{System.out.println("不支持的形态");}}}

通过客户端来模拟一下效果

public static void main(String[] args) {Peiqianhu peiqianhu = new Peiqianhu();// 开始形态为人形态peiqianhu.changeState(Peiqianhu.PeiqianhuShapeState.HUMAN);// 普通攻击peiqianhu.normalAttack();// 释放一技能peiqianhu.releaseFirstSkill();// 释放二技能peiqianhu.releaseSecondSkill();// 释放三技能(变身)peiqianhu.releaseThirdSkill();// 普通攻击peiqianhu.normalAttack();// 释放一技能peiqianhu.releaseFirstSkill();// 释放二技能peiqianhu.releaseSecondSkill();// 释放三技能(变身)peiqianhu.releaseThirdSkill();// 普通攻击peiqianhu.normalAttack();}

运行后输出如下:

【人形态 - 普攻】远程气波攻击
【人形态 - 一技能 - 冲拳式】朝指定方向发出气功波
【人形态 - 二技能 - 气守式】施展念气,产生护盾
【人形态 - 三技能 - 虎啸风生】变身为虎形态
【虎形态 - 普攻】近距离爪击攻击
【虎形态 - 一技能 - 虎啸式】对一名敌人发起撕咬
【虎形态 - 二技能 - 虎跃式】朝指定方向冲刺
【虎形态 - 三技能 - 形意六合】变身为人形态
【人形态 - 普攻】远程气波攻击

看起来还是挺简单的,但是,用这种方式实现会存在一个问题,如果裴擒虎增加一个新形态,比如猫形态,就需要在各个方法中修改if-else结构,这样会非常的不方便。

再来看下通过状态模式的实现方式

定义抽象状态类,声明每种形态下裴擒虎的操作。

/*** 封装裴擒虎不同形态下的操作内容*/
public abstract class PeiqianhuShapeState {protected Peiqianhu peiqianhu;public void setPeiqianhu(Peiqianhu peiqianhu) {this.peiqianhu = peiqianhu;}/*** 普通攻击*/abstract void normalAttack();/*** 释放一技能*/abstract void releaseFirstSkill();/*** 释放二技能*/abstract void releaseSecondSkill();/*** 释放三技能(大招)*/abstract void releaseThirdSkill();}

人形态的实现类

/*** 裴擒虎人形态*/
public class PeiqianhuHumanShapeState extends PeiqianhuShapeState{@Overridepublic void normalAttack() {System.out.println("【人形态 - 普攻】远程气波攻击");}@Overridepublic void releaseFirstSkill() {System.out.println("【人形态 - 一技能 - 冲拳式】朝指定方向发出气功波");}@Overridepublic void releaseSecondSkill() {System.out.println("【人形态 - 二技能 - 气守式】施展念气,产生护盾");}@Overridepublic void releaseThirdSkill() {System.out.println("【人形态 - 三技能 - 虎啸风生】变身为虎形态");super.peiqianhu.changeState(new PeiqianhuTigerShapeState());}
}

虎形态的实现类

/*** 裴擒虎虎形态*/
public class PeiqianhuTigerShapeState extends PeiqianhuShapeState{@Overridepublic void normalAttack() {System.out.println("【虎形态 - 普攻】近距离爪击攻击");}@Overridepublic void releaseFirstSkill() {System.out.println("【虎形态 - 一技能 - 虎啸式】对一名敌人发起撕咬");}@Overridepublic void releaseSecondSkill() {System.out.println("【虎形态 - 二技能 - 虎跃式】朝指定方向冲刺");}@Overridepublic void releaseThirdSkill() {System.out.println("【虎形态 - 三技能 - 形意六合】变身为人形态");super.peiqianhu.changeState(new PeiqianhuHumanShapeState());}
}

定义裴擒虎类,类中持有当前所属的形态,并且可以切换形态

/*** 裴擒虎*/
public class Peiqianhu {/*** 裴擒虎当前形态*/private PeiqianhuShapeState peiqianhuShapeState;/*** 更换形态*/public void changeState(PeiqianhuShapeState peiqianhuShapeState){this.peiqianhuShapeState = peiqianhuShapeState;// 通知到实现类中去this.peiqianhuShapeState.setPeiqianhu(this);}/*** 普通攻击*/public void normalAttack() {peiqianhuShapeState.normalAttack();}/*** 释放一技能*/public void releaseFirstSkill() {peiqianhuShapeState.releaseFirstSkill();}/*** 释放二技能*/public void releaseSecondSkill() {peiqianhuShapeState.releaseSecondSkill();}/*** 释放三技能*/public void releaseThirdSkill() {peiqianhuShapeState.releaseThirdSkill();}}

再来通过客户端来模拟一下效果

public static void main(String[] args) {Peiqianhu peiqianhu = new Peiqianhu();// 开始形态为人形态peiqianhu.changeState(new PeiqianhuHumanShapeState());// 普通攻击peiqianhu.normalAttack();// 释放一技能peiqianhu.releaseFirstSkill();// 释放二技能peiqianhu.releaseSecondSkill();// 释放三技能(变身)peiqianhu.releaseThirdSkill();// 普通攻击peiqianhu.normalAttack();// 释放一技能peiqianhu.releaseFirstSkill();// 释放二技能peiqianhu.releaseSecondSkill();// 释放三技能(变身)peiqianhu.releaseThirdSkill();// 普通攻击peiqianhu.normalAttack();}

运行后输出如下:

【人形态 - 普攻】远程气波攻击
【人形态 - 一技能 - 冲拳式】朝指定方向发出气功波
【人形态 - 二技能 - 气守式】施展念气,产生护盾
【人形态 - 三技能 - 虎啸风生】变身为虎形态
【虎形态 - 普攻】近距离爪击攻击
【虎形态 - 一技能 - 虎啸式】对一名敌人发起撕咬
【虎形态 - 二技能 - 虎跃式】朝指定方向冲刺
【虎形态 - 三技能 - 形意六合】变身为人形态
【人形态 - 普攻】远程气波攻击

通过输出可以看出,使用状态模式和不使用模式,都可以达到相同的效果。

但如果使用状态模式的情况下,再新增加一种形态,如猫形态,我们可以新定义一个猫形态的状态类,然后简单修改下释放三技能变身那块的逻辑,不用每个方法都修改if-else逻辑,这样就方便多了。

四、状态模式的优缺点

优点:

  • 简化应用逻辑控制。 使用单独的类来封装一个状态的处理,使得代码结构和意图更清晰。减少if-else,避免出现巨大的条件语句。
  • 更好的扩展性。 扩展新状态时,只需要新增加一个状态实现类,然后在状态维护或切换的地方简单处理一下即可。
  • 显示化进行状态转换。 状态模式为不同的状态引入独立的对象,使得状态的转换变得更加明确。

缺点:

  • 一个状态一个处理类,如果状态太多,会增加很多类对象。
  • 状态模式对"开闭原则"的支持并不完美,当增加新的状态类时,还是需要修改那些负责状态转换的源代码逻辑。

五、状态模式的应用场景及案例

  • 行为随状态改变而改变的场景。
  • 条件、分支判断语句的替代者。
  • 工作流的设计。

Java设计模式及应用场景之《状态模式》相关推荐

  1. Java设计模式之行为型:状态模式

    背景: 介绍状态模式前,我们先看这样一个实例:公司力排万难终于获得某个酒店的系统开发项目,并且最终落到了你的头上.下图是他们系统的主要工作: 当第一眼看到这个系统时你就看出这是一个状态图,每个框都代表 ...

  2. 【每天一个java设计模式(十七)】 - 状态模式

    在状态模式中,类的行为是基于它的状态改变的,允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类.这种类型的设计模式属于行为型模式. 在状态模式中,我们创建表示各种状态的对象和一个行为 ...

  3. 颜值10分姐姐带我玩转java设计模式(内附照片)- 状态模式

    先不说话,直接来张姐姐照片,称呼上官姐姐即可,希望上官姐姐能带飞 原创不易,麻烦先三连,再细看,谢谢 示例的源码可以直接通过csdn下载也可以通过git导出:https://github.com/ig ...

  4. Java设计模式之行为型:解释器模式

    一.什么是解释器模式:         解释器模式,就是定义语言的文法,并建立一个解释器来解释该语言中的句子,通过构建解释器,解决某一频繁发生的特定类型问题实例. 这里我们将语言理解成使用规定格式和语 ...

  5. Java设计模式之行为型:访问者模式

    背景: 去医院看病时,医生会给你一个处方单要你去拿药,拿药我们可以分为两步走: (1)去柜台交钱,划价人员会根据处方单上的药进行划价,交钱. (2)去药房拿药,药房工作者同样根据处方单给你相对应的药. ...

  6. Java设计模式之行为型:备忘录模式

    在开发过程中,经常需要保存对象的中间状态,当需要的时候,可以恢复到这个状态.比如,在编程时假如编写失误,例如不小心误删除了几行代码,我们希望返回删除前的状态,便可以使用 Ctrl+Z 来进行返回,这时 ...

  7. Java设计模式之行为型:命令模式

    前言: 在开发中,我们可能需要向某些对象发送一些请求,但我们不知道请求的具体接收者是谁,也不知道被请求的操作是哪个,只知道在系统运行中指定具体的请求接收者即可,打个比方,电视遥控器,我们只需知道按哪个 ...

  8. Java设计模式之行为型:迭代器模式

    一.什么是迭代器模式: 实际开发中,我们针对不同的需求,可能需要以不同的方式来遍历整个整合对象,但我们不希望在集合容器的抽象接口层中充斥着各种不同的遍历操作,这时候我们就需要一种能完成下面功能的迭代器 ...

  9. Java设计模式之行为型:策略模式

    一.背景: 在开发中经常遇到这种情况,实现某个功能有多种算法策略,我们可以根据不同环境或者条件选择不同的算法策略来完成该功能,比如查找.排序等,一种常用方式是硬编码在一个类中,如需要提供多种查找算法, ...

  10. Java设计模式之结构型:外观模式

    一.什么是外观模式: 外观模式通过对客户端提供一个统一的接口,用于访问子系统中的一群接口.使用外观模式有以下几点好处: (1)更加易用:使得子系统更加易用,客户端不再需要了解子系统内部的实现,也不需要 ...

最新文章

  1. 常见的http状态码总结。
  2. SpringMVC怎么获取前台传来的数组
  3. pycharm安装怎么选_客厅窗帘怎么选 客厅窗帘怎么安装好看
  4. 巧做辅助线计算三角形角的度数
  5. c 中oracle连接字符串,Oracle连接字符串C#
  6. 王道考研 计算机网络4 速率相关的性能指标
  7. Map集合-根据宠物昵称查找宠物
  8. 【图像处理】【去模糊】代码资源汇总
  9. 【河马】oracle注入工具v1.1,明小子4.5|明小子注入工具 v15.1最新版
  10. kettle-连接mysql数据库
  11. Faster RCNN论文总结
  12. mysql分页查询非常慢_MySQL分页查询慢的原因及解决方案
  13. 5个提供flickr高级图片搜索的网站
  14. GSOAP 在一个客户端内调用多个服务出现的问题解决
  15. Python实战回归模型-消费者人群画像-信用智能评分(基于中国移动用户数据)
  16. 莫队算法 --算法竞赛专题解析(26)
  17. 两个三维图像互信息python_含有两个数字的词语
  18. APIO2019 打铁记
  19. html请求资源不可用,HTTP状态404 – 请求的资源(/)不可用
  20. 短视频美食系列都有哪些变现方式?丨国仁网络资讯

热门文章

  1. elementUI 框架组件
  2. java flip方法_Python numpy.flip函数方法的使用
  3. Java工厂模式与抽象工厂模式
  4. pytorch tensor flip
  5. 二分法-续-入门基础
  6. 二十几岁的你,为什么记忆力越来越差?
  7. 九州云亮相OpenInfra Days China,荣获“社区卓越领导力奖”
  8. 金立M7怎么升级鸿蒙系统,一周头条:金立M7发布 华为Mate10爆猛料
  9. 提前让大家享受下7月22号合肥日食(图)
  10. 系统学习NLP(二十一)--关键词提取算法总结