应用程序中的有些对象可能会根据不同的情况做出不同的行为,我们把这种对象称为有状态的对象,而把影响对象行为的一个或多个动态变化的属性称为状态。当有状态的对象与外部事件产生互动时,其内部状态会发生改变,从而使得其行为也随之发生改变。
状态(State)模式的定义:对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
状态模式的解决思想是:当控制一个对象状态转换的条件表达式过于复杂时,把相关“判断逻辑”提取出来,放到一系列的状态类当中,这样可以把原来复杂的逻辑判断简单化。
状态模式是一种对象行为型模式,其主要优点如下:
状态模式的主要缺点如下:
状态模式把受环境改变的对象行为包装在不同的状态对象里,其意图是让一个对象在其内部状态改变的时候,其行为也随之改变。现在我们来分析其基本结构和实现方法。
状态模式包含以下主要角色:
其结构图如图所示:
代码实现如下:
public class StatePatternClient { public static void main(String[] args) { Context context=new Context(); //创建环境 context.Handle(); //处理请求 context.Handle(); context.Handle(); context.Handle(); } } //环境类 class Context { private State state; //定义环境类的初始状态 public Context() { this.state=new ConcreteStateA(); } //设置新状态 public void setState(State state) { this.state=state; } //读取状态 public State getState() { return(state); } //对请求做处理 public void Handle() { state.Handle(this); } } //抽象状态类 abstract class State { public abstract void Handle(Context context); } //具体状态A类 class ConcreteStateA extends State { public void Handle(Context context) { System.out.println("当前状态是 A."); context.setState(new ConcreteStateB()); } } //具体状态B类 class ConcreteStateB extends State { public void Handle(Context context) { System.out.println("当前状态是 B."); context.setState(new ConcreteStateA()); } }
运行结果如下:
当前状态是 A.
当前状态是 B.
当前状态是 A.
当前状态是 B.
用“状态模式”设计一个学生成绩的状态转换程序:多线程存在 5 种状态,分别为新建状态、就绪状态、运行状态、阻塞状态和死亡状态,各个状态当遇到相关方法调用或事件触发时会转换到其他状态,其状态转换规律如图所示:
现在先定义一个抽象状态类(TheadState),然后为上图所示的每个状态设计一个具体状态类,它们是新建状态(New)、就绪状态(Runnable )、运行状态(Running)、阻塞状态(Blocked)和死亡状态(Dead),每个状态中有触发它们转变状态的方法,环境类(ThreadContext)中先生成一个初始状态(New),并提供相关触发方法,线程状态转换程序的结构图如下图所示:
代码如下:
public class ThreadStateTest { public static void main(String[] args) { ThreadContext context=new ThreadContext(); context.start(); context.getCPU(); context.suspend(); context.resume(); context.getCPU(); context.stop(); } } //环境类 class ThreadContext { private ThreadState state; ThreadContext() { state=new New(); } public void setState(ThreadState state) { this.state=state; } public ThreadState getState() { return state; } public void start() { ((New) state).start(this); } public void getCPU() { ((Runnable) state).getCPU(this); } public void suspend() { ((Running) state).suspend(this); } public void stop() { ((Running) state).stop(this); } public void resume() { ((Blocked) state).resume(this); } } //抽象状态类:线程状态 abstract class ThreadState { protected String stateName; //状态名 } //具体状态类:新建状态 class New extends ThreadState { public New() { stateName="新建状态"; System.out.println("当前线程处于:新建状态."); } public void start(ThreadContext hj) { System.out.print("调用start()方法-->"); if(stateName.equals("新建状态")) { hj.setState(new Runnable()); } else { System.out.println("当前线程不是新建状态,不能调用start()方法."); } } } //具体状态类:就绪状态 class Runnable extends ThreadState { public Runnable() { stateName="就绪状态"; System.out.println("当前线程处于:就绪状态."); } public void getCPU(ThreadContext hj) { System.out.print("获得CPU时间-->"); if(stateName.equals("就绪状态")) { hj.setState(new Running()); } else { System.out.println("当前线程不是就绪状态,不能获取CPU."); } } } //具体状态类:运行状态 class Running extends ThreadState { public Running() { stateName="运行状态"; System.out.println("当前线程处于:运行状态."); } public void suspend(ThreadContext hj) { System.out.print("调用suspend()方法-->"); if(stateName.equals("运行状态")) { hj.setState(new Blocked()); } else { System.out.println("当前线程不是运行状态,不能调用suspend()方法."); } } public void stop(ThreadContext hj) { System.out.print("调用stop()方法-->"); if(stateName.equals("运行状态")) { hj.setState(new Dead()); } else { System.out.println("当前线程不是运行状态,不能调用stop()方法."); } } } //具体状态类:阻塞状态 class Blocked extends ThreadState { public Blocked() { stateName="阻塞状态"; System.out.println("当前线程处于:阻塞状态."); } public void resume(ThreadContext hj) { System.out.print("调用resume()方法-->"); if(stateName.equals("阻塞状态")) { hj.setState(new Runnable()); } else { System.out.println("当前线程不是阻塞状态,不能调用resume()方法."); } } } //具体状态类:死亡状态 class Dead extends ThreadState { public Dead() { stateName="死亡状态"; System.out.println("当前线程处于:死亡状态."); } }
测试结果如下:
当前线程处于:新建状态. 调用start()方法-->当前线程处于:就绪状态. 获得CPU时间-->当前线程处于:运行状态. 调用suspend()方法-->当前线程处于:阻塞状态. 调用resume()方法-->当前线程处于:就绪状态. 获得CPU时间-->当前线程处于:运行状态. 调用stop()方法-->当前线程处于:死亡状态.
通常在以下情况下可以考虑使用状态模式。
在有些情况下,可能有多个环境对象需要共享一组状态,这时需要引入享元模式,将这些具体状态对象放在集合中供程序共享,其结构图如图所示:
共享状态模式的不同之处是在环境类中增加了一个 HashMap 来保存相关状态,当需要某种状态时可以从中获取,其程序代码如下:
public class FlyweightStatePattern { public static void main(String[] args) { ShareContext context=new ShareContext(); //创建环境 context.Handle(); //处理请求 context.Handle(); context.Handle(); context.Handle(); } } //环境类 class ShareContext { private ShareState state; private HashMap<String, ShareState> stateSet=new HashMap<String, ShareState>(); public ShareContext() { state=new ConcreteState1(); stateSet.put("1", state); state=new ConcreteState2(); stateSet.put("2", state); state=getState("1"); } //设置新状态 public void setState(ShareState state) { this.state=state; } //读取状态 public ShareState getState(String key) { ShareState s=(ShareState)stateSet.get(key); return s; } //对请求做处理 public void Handle() { state.Handle(this); } } //抽象状态类 abstract class ShareState { public abstract void Handle(ShareContext context); } //具体状态1类 class ConcreteState1 extends ShareState { public void Handle(ShareContext context) { System.out.println("当前状态是: 状态1"); context.setState(context.getState("2")); } } //具体状态2类 class ConcreteState2 extends ShareState { public void Handle(ShareContext context) { System.out.println("当前状态是: 状态2"); context.setState(context.getState("1")); } }
执行结果如下:
当前状态是: 状态1
当前状态是: 状态2
当前状态是: 状态1
当前状态是: 状态2
原文:https://www.cnblogs.com/jing99/p/12610105.html