状态模式

编程入门 行业动态 更新时间:2024-10-10 21:24:30

<a href=https://www.elefans.com/category/jswz/34/1771386.html style=状态模式"/>

状态模式

文章目录

  • 变身药丸
  • 黑崎一护的变身状态一览
    • 正常状态
    • 始解状态
    • 卍解状态
    • 虚化状态
  • 普通的实现方法
  • 使用状态模式
  • 总结
    • 状态模式的优点
    • 状态模式的缺点

变身药丸

黑崎一护在和蓝染战斗中,使用了最后的月牙天冲重创蓝染,最终被被浦原喜助使用封印封锁。

一护立下大功,同时也丧失了死神的力量,无法使用斩魂刀变身了。

十二番队长涅茧利为了感谢一户,苦心研发了能够暂时获得死神能力的三种药丸:初解药丸,卍解药丸和虚化药丸。

这三种药丸服用之后能够变身成相应的状态,同时拥有对应的必杀技,战斗力大大增强。

黑崎一护的变身状态一览

正常状态

战斗力指数:100

始解状态

战斗力指数:200

卍解状态

战斗力指数:500

虚化状态

战斗力指数:1000

十二番队长涅茧利特意嘱咐了下用药规则,正常状态下只有吃始解药丸和卍解药丸才有作用,虚化药丸只有在卍解状态下吃才有作用,还有,同一种药丸重复吃是没有用的,不要浪费哦。

​另外,变身状态下,使用了必杀技之后,药效就会消失,立即恢复到正常状态,要注意哦,副队长涅音梦提醒道。

贴心的副队长涅音梦还画了幅状态转换图:

普通的实现方法

状态枚举类

public enum State {/*** 正常状态*/NORMAL(0),/*** 始解状态*/INITIAL(1),/*** 卍解状态*/SWASTIKA(2),/*** 虚化状态*/BLUR(3);private int value;private State(int value) {this.value = value;}public int getValue() {return this.value;}
}

变身状态机类

public class TransformStateMachine {/*** 战斗力*/private int fightingPower;/*** 当前状态*/private State currentState;public int getFightingPower() {return this.fightingPower;}public State getCurrentState() {return this.currentState;}/*** 初始化*/public TransformStateMachine() {this.fightingPower = 100;this.currentState = State.NORMAL;}/*** 吃下始解药丸*/public void eateInitialPill() {System.out.println("吃下始解药丸");if(currentState.equals(State.NORMAL)) {this.currentState = State.INITIAL;this.fightingPower += 200;System.out.println("**变身始解状态**战斗力加200");} else {System.out.println("木有任何变化。。。");}}/*** 吃下卍解药丸*/public void eateSwastikaPill() {System.out.println("吃下卍解药丸");if(currentState.equals(State.NORMAL) || currentState.equals(State.INITIAL)) {this.currentState = State.SWASTIKA;this.fightingPower += 500;System.out.println("**变身卍解状态**战斗力加500");} else {System.out.println("木有任何变化。。。");}}/*** 吃下虚化药丸*/public void eateBlurPill() {System.out.println("吃下虚化药丸");if(currentState.equals(State.SWASTIKA)) {this.currentState = State.BLUR;this.fightingPower += 1000;System.out.println("**变身虚化状态**战斗力加1000");} else {System.out.println("木有任何变化。。。");}}/*** 使用必杀技*/public void useUniqueSkill() {System.out.println("使用必杀技");if(currentState.equals(State.INITIAL) || currentState.equals(State.SWASTIKA) || currentState.equals(State.BLUR)) {System.out.println("月牙天冲--->");this.currentState = State.NORMAL;this.fightingPower = 100;System.out.println("**变回初始状态**战斗力变成100");} else {System.out.println("木有任何变化。。。");}}
}

测试类

public class Test {public static void main(String[] args) {TransformStateMachine transformStateMachine = new TransformStateMachine();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');transformStateMachine.eateInitialPill();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');transformStateMachine.eateSwastikaPill();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');transformStateMachine.eateBlurPill();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');transformStateMachine.useUniqueSkill();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');transformStateMachine.useUniqueSkill();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');}
}

运行结果

当前状态: NORMAL; 战斗力指数: 100吃下始解药丸
**变身始解状态**战斗力加200
当前状态: INITIAL; 战斗力指数: 300吃下卍解药丸
**变身卍解状态**战斗力加500
当前状态: SWASTIKA; 战斗力指数: 800吃下虚化药丸
**变身虚化状态**战斗力加1000
当前状态: BLUR; 战斗力指数: 1800使用必杀技
月牙天冲--->
**变回初始状态**战斗力变成100
当前状态: NORMAL; 战斗力指数: 100使用必杀技
木有任何变化。。。
当前状态: NORMAL; 战斗力指数: 100

如果是简单的状态转换来说,这种方式是最简单直接的首选方法。

如果状态很多,这样编写的代码会包含大量的 if-else 或 switch-case 分支判断逻辑,可读性和可维护性都很差。

而且不符合开闭原则,如果修改了状态机中的某个状态转移,我们要在冗长的分支逻辑中找到对应的代码进行修改,很容易改错,引入 bug。

使用状态模式

我们要重构一下上面的代码,试着把每个状态的行为封装到一个类里,“封装了变化”,这样能让逻辑和结构更加清晰。

而且,我们针对某个状态的改变就不会影响其他的状态了,让修改和维护更容易。

这时候就要请状态模式出马了。

状态模式(State Pattern) :允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。


本例的类图如下:

状态枚举类

public enum State {/*** 正常状态*/NORMAL(0),/*** 始解状态*/INITIAL(1),/*** 卍解状态*/SWASTIKA(2),/*** 虚化状态*/BLUR(3);private int value;private State(int value) {this.value = value;}public int getValue() {return this.value;}
}

状态类接口

public interface ITransformState {/*** 获取当前状态* @return*/State getState();/*** 吃下始解药丸*/void eateInitialPill();/*** 吃下卍解药丸*/void eateSwastikaPill();/*** 吃下虚化药丸*/void eateBlurPill();/*** 使用必杀技*/void useUniqueSkill();
}

初始状态实现类

public class NormalTransform implements ITransformState{private TransformStateMachine transformStateMachine;public NormalTransform(TransformStateMachine transformStateMachine) {this.transformStateMachine = transformStateMachine;}/*** 获取当前状态* @return*/public State getState() {return State.NORMAL;}/*** 吃下始解药丸*/public void eateInitialPill() {System.out.println("吃下始解药丸");transformStateMachine.setCurrentState(new InitialTransform(transformStateMachine));transformStateMachine.setFightingPower(transformStateMachine.getFightingPower() + 200);System.out.println("**变身始解状态**战斗力加200");}/*** 吃下卍解药丸*/public void eateSwastikaPill() {System.out.println("吃下卍解药丸");transformStateMachine.setCurrentState(new SwastikaTransform(transformStateMachine));transformStateMachine.setFightingPower(transformStateMachine.getFightingPower() + 500);System.out.println("**变身卍解状态**战斗力加500");}/*** 吃下虚化药丸*/public void eateBlurPill() {System.out.println("吃下虚化药丸");System.out.println("木有任何变化。。。");}/*** 使用必杀技*/public void useUniqueSkill() {System.out.println("使用必杀技");System.out.println("木有任何变化。。。");}
}

始解状态实现类

public class InitialTransform implements ITransformState{private TransformStateMachine transformStateMachine;public InitialTransform(TransformStateMachine transformStateMachine) {this.transformStateMachine = transformStateMachine;}/*** 获取当前状态* @return*/public State getState() {return State.INITIAL;}/*** 吃下始解药丸*/public void eateInitialPill() {System.out.println("吃下始解药丸");System.out.println("木有任何变化。。。");}/*** 吃下卍解药丸*/public void eateSwastikaPill() {System.out.println("吃下卍解药丸");transformStateMachine.setCurrentState(new SwastikaTransform(transformStateMachine));transformStateMachine.setFightingPower(transformStateMachine.getFightingPower() + 500);System.out.println("**变身卍解状态**战斗力加500");}/*** 吃下虚化药丸*/public void eateBlurPill() {System.out.println("吃下虚化药丸");System.out.println("木有任何变化。。。");}/*** 使用必杀技*/public void useUniqueSkill() {System.out.println("使用必杀技");System.out.println("月牙天冲--->");transformStateMachine.setCurrentState(new NormalTransform(transformStateMachine));transformStateMachine.setFightingPower(100);System.out.println("**变回初始状态**战斗力变成100");}
}

卍解状态实现类

public class SwastikaTransform implements ITransformState {private TransformStateMachine transformStateMachine;public SwastikaTransform(TransformStateMachine transformStateMachine) {this.transformStateMachine = transformStateMachine;}/*** 获取当前状态* @return*/public State getState() {return State.SWASTIKA;}/*** 吃下始解药丸*/public void eateInitialPill() {System.out.println("吃下始解药丸");System.out.println("木有任何变化。。。");}/*** 吃下卍解药丸*/public void eateSwastikaPill() {System.out.println("吃下始解药丸");System.out.println("木有任何变化。。。");}/*** 吃下虚化药丸*/public void eateBlurPill() {System.out.println("吃下虚化药丸");transformStateMachine.setCurrentState(new BlurTransform(transformStateMachine));transformStateMachine.setFightingPower(transformStateMachine.getFightingPower() + 1000);System.out.println("**变身虚化状态**战斗力加1000");}/*** 使用必杀技*/public void useUniqueSkill() {System.out.println("使用必杀技");System.out.println("黑流牙突--->");transformStateMachine.setCurrentState(new NormalTransform(transformStateMachine));transformStateMachine.setFightingPower(100);System.out.println("**变回初始状态**战斗力变成100");}
}

虚化状态实现类

public class BlurTransform implements ITransformState {private TransformStateMachine transformStateMachine;public BlurTransform(TransformStateMachine transformStateMachine) {this.transformStateMachine = transformStateMachine;}/*** 获取当前状态* @return*/public State getState() {return State.BLUR;}/*** 吃下始解药丸*/public void eateInitialPill() {System.out.println("吃下始解药丸");System.out.println("木有任何变化。。。");}/*** 吃下卍解药丸*/public void eateSwastikaPill() {System.out.println("吃下卍解药丸");System.out.println("木有任何变化。。。");}/*** 吃下虚化药丸*/public void eateBlurPill() {System.out.println("吃下虚化药丸");System.out.println("木有任何变化。。。");}/*** 使用必杀技*/public void useUniqueSkill() {System.out.println("使用必杀技");System.out.println("王虚的闪光--->");transformStateMachine.setCurrentState(new NormalTransform(transformStateMachine));transformStateMachine.setFightingPower(100);System.out.println("**变回初始状态**战斗力变成100");}
}

变身状态机类

public class TransformStateMachine {/*** 战斗力*/private int fightingPower;/*** 当前状态*/private ITransformState currentState;/*** 初始化*/public TransformStateMachine() {this.fightingPower = 100;this.currentState = new NormalTransform(this);}/*** 吃下始解药丸*/public void eateInitialPill() {this.currentState.eateInitialPill();}/*** 吃下卍解药丸*/public void eateSwastikaPill() {this.currentState.eateSwastikaPill();}/*** 吃下虚化药丸*/public void eateBlurPill() {this.currentState.eateBlurPill();}/*** 使用必杀技*/public void useUniqueSkill() {this.currentState.useUniqueSkill();}public int getFightingPower() {return this.fightingPower;}public void setFightingPower(int fightingPower) {this.fightingPower = fightingPower;}public State getCurrentState() {return this.currentState.getState();}public void setCurrentState(ITransformState currentState) {this.currentState = currentState;}
}

测试类

public class Test {public static void main(String[] args) {TransformStateMachine transformStateMachine = new TransformStateMachine();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');transformStateMachine.eateInitialPill();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');transformStateMachine.eateBlurPill();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');transformStateMachine.eateSwastikaPill();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');transformStateMachine.eateBlurPill();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');transformStateMachine.useUniqueSkill();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');transformStateMachine.eateSwastikaPill();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');transformStateMachine.useUniqueSkill();System.out.println("当前状态: " + transformStateMachine.getCurrentState() + "; 战斗力指数: " + transformStateMachine.getFightingPower() + '\n');}
}

测试结果

当前状态: NORMAL; 战斗力指数: 100吃下始解药丸
**变身始解状态**战斗力加200
当前状态: INITIAL; 战斗力指数: 300吃下虚化药丸
木有任何变化。。。
当前状态: INITIAL; 战斗力指数: 300吃下卍解药丸
**变身卍解状态**战斗力加500
当前状态: SWASTIKA; 战斗力指数: 800吃下虚化药丸
**变身虚化状态**战斗力加1000
当前状态: BLUR; 战斗力指数: 1800使用必杀技
王虚的闪光--->
**变回初始状态**战斗力变成100
当前状态: NORMAL; 战斗力指数: 100吃下卍解药丸
**变身卍解状态**战斗力加500
当前状态: SWASTIKA; 战斗力指数: 600使用必杀技
黑流牙突--->
**变回初始状态**战斗力变成100
当前状态: NORMAL; 战斗力指数: 100

总结

状态模式一般用来实现有限状态机。

有限状态机的英文翻译是 Finite State Machine,缩写为 FSM,简称为状态机。

状态机有 3 个组成部分:状态(State)、事件(Event)、动作(Action)。其中,事件也称为转移条件(Transition Condition)。事件触发状态的转移及动作的执行。

不过,动作不是必须的,也可能只转移状态,不执行任何动作。

状态机的状态随着某种事件的发生而改变,事件就是状态转移的条件,状态转移时可能会有相应的操作要同时进行。

状态模式的优点

1.如果状态变更伴随着复杂的操作,状态模式能把所有操作封装到一个类里,允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。

2.把每个状态和动作提取出来,封装到一个类中,就把着眼点从执行状态提高到整个对象的状态,这将使代码更加结构化,整体意图更加清晰。

3.以后对状态的修改之需要修改一个子类,新增一个新的状态,只需要新增一个状态类,对原有代码的修改少。

状态模式的缺点

1.会增加系统类和对象的个数。

2.一个State的子类至少拥有一个其他子类的信息,各个子类之间产生了依赖。

代码链接












更多推荐

状态模式

本文发布于:2024-02-07 13:01:11,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1757005.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:状态   模式

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!