一、背景
最近系统的学习一下Java设计模式,下了2本电子书,《设计模式之禅》与《Head First 设计模式》,支持国产嘛,先看《设计模式之禅》,首先说一下对它的感觉,叙述比较简洁明了,举例很有趣味性、贴切,吸引人,有很多对比的例子(不采用设计模式和采用设计模式),对初学者来说还不错。有一个小遗憾就是:作者所画的类图有时并没有和代码对应。今天看到状态模式了,突然想来记录点什么,所以这篇博文就诞生了。
二、状态分析
还是拿作者的例子――电梯,电梯有四种动作:开门,关门,运行,停止。对应四种状态:门敞状态,门闭状态,运行状态,停止状态,它们之间的关系如下:
开门(open) | 关门(close) | 运行(run) | 停止(stop) | |
门敞状态 | no | ok | no | no |
门闭状态 | ok | no | ok | ok |
运行状态 | no | no | no | ok |
停止状态 | ok | no | ok | no |
三、画出类图
才刚开始学画类图了,采用的工具是starUML,如下:
四、代码
在类图基础上,利用starUML自动生成代码,然后再修改而成了。
1、环境封装类Context
public class Context { private LiftState liftState; public LiftState getLiftState() { return this.liftState; } public void setListState(LiftState liftState) { liftState.setContext(this); this.liftState = liftState; } public void open() { this.liftState.open(); } public void close() { this.liftState.close(); } public void run() { this.liftState.run(); } public void stop() { this.liftState.stop(); } }
2、状态抽象类LiftState
public abstract class LiftState { protected Context context; public void setContext(Context _context) { this.context = _context; } public abstract void open(); public abstract void close(); public abstract void run(); public abstract void stop(); }
3、四种状态类和状态池类OpenningState,ClosingState,RunningState,StoppingState,StatesPools
(1)OpenningState
public class OpenningState extends LiftState { public void open() { //已经打开了,不做任何操作 } public void close() { //打开状态,是可以关闭的 System.out.println("关闭电梯..."); super.context.setListState(StatesPool.closingState); } public void run() { //开的时候,当然是不能跑的 } public void stop() { //开的时候,也没必要停 } }
(2)ClosingState
public class ClosingState extends LiftState { public void open() { //关闭了当然是可以打开的 System.out.println("电梯打开"); super.context.setListState(StatesPool.openningState); } public void close() { //已经关闭了 } public void run() { //关闭当然是可以运行的 System.out.println("电梯运行"); super.context.setListState(StatesPool.runningState); } public void stop() { //关闭也可以停止的 System.out.println("电梯停止"); super.context.setListState(StatesPool.stoppingState); } }
(3)RunningState
public class RunningState extends LiftState { public void open() { //正在运行的时候不能开 } public void close() { //正在运行的时候不能关 } public void run() { //已经在运行了 } public void stop() { //运行时候,当然是可以停的 System.out.println("停止电梯..."); // 改变状态 super.context.setListState(StatesPool.stoppingState); } }
(4)StoppingState
public class StoppingState extends LiftState { public void open() { //停止状态下可以打开啦 System.out.println("电梯打开"); super.context.setListState(StatesPool.openningState); } public void close() { } public void run() { //停止状态下可以继续运行了 System.out.println("电梯运行"); super.context.setListState(StatesPool.runningState); } public void stop() { } }
(5)StatesPools
public class StatesPool { public static final OpenningState openningState = new OpenningState(); public static final ClosingState closingState = new ClosingState(); public static final RunningState runningState = new RunningState(); public static final StoppingState stoppingState = new StoppingState(); }
4、客户端调用类Client
public class Client { public static void main(String[] args) { Context context = new Context(); context.setListState(new ClosingState()); context.open(); context.close(); context.run(); context.stop(); context.open(); } }
5、运行结果
电梯打开 关闭电梯... 电梯运行 停止电梯... 电梯打开
五、总结
行为与状态有对应关系,状态的切换伴随着相应的行为,都可以用状态模式了。另外抱怨51cto一句:再做好一点行不行啊,每次贴代码都要我重新选择语言,上面贴的代码都选了n次Java了,就不能帮我记住吗?
ps:代码地址http://down.51cto.com/data/1029676