状态模式
一、定义
状态模式:对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
二、特点
优点:
- 封装了转换规则并且将不同状态的行为分割开来。(满足“单一职责原则”)
- 减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换
缺点:
- 状态模式的使用必然会增加系统的类与对象的个数。
- 状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。
模式扩展:
在有些情况下,可能有多个环境对象需要共享一组状态,这时需要引入享元模式,将这些具体状态对象放在集合中供程序共享。
三、使用场景
1.状态模式在工作流或游戏等类型的软件中得以广泛使用,甚至可以用于这些系统的核心功能设计,如在政府0A办公系统中,一个批文的状态有多种:尚未办理;正在办理;正在批示;正在审核;已经完成等各种状态。使用状态模式可以描述工作流对象(如批文)的状态转换以及不同状态下它所具有的行为。
2.在目前主流的RPG (Role Play Game,角色扮演游戏)中,使用状态模式可以对游戏角色进行控制,游戏角色的升级伴随着其状态的变化和行为的变化。对于游戏程序本身也可以通过状态模式进行总控,一个游戏活动包括开始、运行、结束等状态,通过对状态的控制可以控制系统的行为,决定游戏的各个方面,因此可以使用状态模式对整个游戏的架构进行设计与实现。
四、类图
角色:
环境(Context). 角色:也称为上下文,它定义了客户感兴趣的接口,维护-一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
抽象状态(State) 角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。
具体状态(Concrete … State)角色:实现抽象状态所对应的行为。
五、实战代码
模拟线程的状态:
【ThreadState.java】
package state;
public abstract class ThreadState {
protected int state; //状态名
}
【StateSet .java】
package state;
public final class StateSet {
//定义了可以用类名引用的全局量
public static int NEW=1;
public static int RANNABLE=2;
public static int RUNNING=3;
public static int BLOCKED=4;
public static int DEAD=5;
}
【ThreadContext.java】
package state;
public class ThreadContext {
private ThreadState threadState;
public ThreadContext(){
threadState=new NewState();
}
public ThreadState getThreadState(){
return threadState;
}
public void setThreadState(ThreadState threadState){
this.threadState=threadState;
}
public void start(){
((NewState)threadState).start(this);
//强制转换 成子类对象,
}
public void getCPU(){
((RunnableState)threadState).getCPU(this);
}
public void suspend(){
((RunningState)threadState).suspend(this);
}
public void stop(){
((RunningState)threadState).stop(this);
}
public void resume(){
((BlockState)threadState).resume(this);
}
}
【NewState.java】
package state;
public class NewState extends ThreadState {
public NewState(){
state=StateSet.NEW;
System.out.println("新建线程");
}
public void start(ThreadContext tc){
System.out.println("调用了Start方法");
if(state==StateSet.NEW)
tc.setThreadState(new RunnableState());
else
System.out.println("当前线程不是新建状态");
}
}
【RunnableState.java】
package state;
public class RunnableState extends ThreadState {
public RunnableState(){
state=StateSet.RANNABLE;
System.out.println("就绪状态");
}
public void getCPU(ThreadContext tc){
System.out.println("获得CPU时间");
if(state==StateSet.RANNABLE)
tc.setThreadState(new RunningState());
else
System.out.println("当前状态不是就绪状态");
}
}
【RunningState.java】
package state;
public class RunningState extends ThreadState {
public RunningState(){
state=StateSet.RUNNING;
System.out.println("运行状态");
}
public void suspend(ThreadContext tc){ //一种情况是阻塞
System.out.println(" 调用suspend方法");
if(state==StateSet.RUNNING)
tc.setThreadState(new BlockState());
else
System.out.println("当前状态不是运行状态");
}
public void stop(ThreadContext tc){
System.out.println("调用stop方法");
if(state==StateSet.RUNNING)
tc.setThreadState(new DeadState());
else
System.out.println("当前状态不是运行状态");
}
}
【BlockState.java】
package state;
public class BlockState extends ThreadState {
public BlockState(){
state=StateSet.BLOCKED;
System.out.println("阻塞线程");
}
public void resume(ThreadContext tc){
System.out.println("调用了resume方法");
if(state==StateSet.BLOCKED){
tc.setThreadState(new NewState());}
else
System.out.println("当前线程不是阻塞状态");
}
}
【DeadState.java】
package state;
public class DeadState extends ThreadState {
public DeadState(){
state=StateSet.DEAD;
System.out.println("线程死亡");
}
}
【ClientClass.java】
package state;
//用户在使用这个状态模式的时候必须得很清楚我们用的状态模式里面有效的切换路径
public class ClientClass {
public static void main(String[] args) {
ThreadContext tc=new ThreadContext();
tc.start();
tc.getCPU();
tc.stop();
}
}
【运行截图】
喜欢的话记得点赞收藏哟😊
Java设计模式—博文专栏持续更新!