java/android 设计模式学习笔记(19)---状态模式
来源:互联网 发布:算法心得 原书 编辑:程序博客网 时间:2024/04/29 13:29
这篇博客我们来介绍一下状态模式(State Pattern),也是行为型设计模式之一。状态模式的行为是由状态来决定的,不同的状态下有不同的行为。状态模式和策略模式的结构类图几乎完全一样,但它们的目的、本质却完全不一样。状态模式的行为是平行的、不可替换的,策略模式的行为是彼此独立、可相互替换的。状态模式把对象的行为包装在不同的状态对象里,每一个状态对象都有一个共同的抽象状态基类;而策略模式可以想象成是除了继承之外的一种弹性替代方案,如果你使用继承定义了一个类的行为,你将被这个行为困住,甚至要修改它都很难,有了策略模式,你可以通过组合不同的对象来改变行为。状态模式的意图是让一个对象在其内部状态发生改变的时候,其行为也随之改变。
转载请注明出处:http://blog.csdn.net/self_study/article/details/52432486。
PS:对技术感兴趣的同鞋加群544645972一起交流。
设计模式总目录
java/android 设计模式学习笔记目录
特点
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式的使用场景:
- 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为;
- 代码中包含大量与状态有关的条件语句,例如,一个操作中含有庞大的多分枝语句(if-else 或者 switch-case),且这些分支依赖于该对象的状态。
UML类图
状态模式的 uml 类图有三个角色:
- Context:环境类,定义客户感兴趣的接口,维护一个 State 子类,这个实例定义了对象的当前状态;
- State:抽象状态类或者状态接口,定义一个或者一组接口,表示该状态下的行为;
- ConcreteStateA、ConcreteStateB:具体状态类,每一个具体的状态类实现抽象的 State 中定义的接口,从而达到不同状态下的不同行为。
状态接口以及相关子类:
State.class
public interface State { void doSomething();}
ConcreteStateA.class、ConcreteStateB.class、NullState.class
public class ConcreteStateA implements State { @Override public void doSomething() { System.out.print("this is ConcreteStateA's function\n"); }}
public class ConcreteStateB implements State{ @Override public void doSomething() { System.out.print("this is ConcreteStateB's function\n"); }}
public class NullState implements State{ @Override public void doSomething() { //do nothing }}
Context类以及测试代码:
Context.class
public class Context { private State state = new NullState(); void setState(State state) { this.state = state; } void doSomething() { state.doSomething(); } public static void main(String[] args) { Context context = new Context(); context.setState(new ConcreteStateA()); context.doSomething(); context.setState(new ConcreteStateB()); context.doSomething(); }}
最后结果:
this is ConcreteStateA's functionthis is ConcreteStateB's function
示例与源码
在 Android 源码中也有很多状态模式的例子,MediaPlayer 和 WifiStateEngine 等,这里我们来简单看看 MediaPlayer 的状态机:
椭圆代表 MediaPlayer 对象可能驻留的状态。弧线表示驱动 MediaPlayer 在各个状态之间迁移的播放控制操作。这里有两种类型的弧线。由一个箭头开始的弧代表同步的方法调用,而以双箭头开头的代表的弧线代表异步方法调用。MediaPlayer在这我就不详细介绍了,网上资料很多,感兴趣的可以去查阅一下。
这里再介绍一下状态机,又称为有限状态自动机 (FSM:Finite State Machine),是表示有限多个状态以及在这些状态之间转移和动作的数学模型。状态存储关于过去的信息,它反映从系统开始到现在时刻输入的变化;转移指示状态变更,用必须满足来确使转移发生的条件来描述它;动作是在给定时刻要进行的活动描述,详细的看看这篇博客:有限状态机(FSM)的Java 演示 。
实际 Android 开发过程中,我们一般会去根据实际情况去先构造一个状态图,定义每个状态和每个状态之间切换的事件,类似于上图的 MediaPlayer,然后将该信息录入进入状态机,当目前的状态接收到一个非法的跳转事件时,可以抛出异常,这样就能保证一切按照预先设定好的方向进行。
Demo
我们这里仍然以 wiki 上的 demo 为例,来实现一堆字符串的一个大小写间隔打印:
Statelike.class
interface Statelike { void writeName(StateContext context, String name);}
StateLowerCase.class 和 StateMultipleUpperCase.class
class StateLowerCase implements Statelike { @Override public void writeName(final StateContext context, final String name) { System.out.println(name.toLowerCase()); context.setState(new StateMultipleUpperCase()); }}
class StateMultipleUpperCase implements Statelike { /** Counter local to this state */ private int count = 0; @Override public void writeName(final StateContext context, final String name) { System.out.println(name.toUpperCase()); /* Change state after StateMultipleUpperCase's writeName() gets invoked twice */ if(++count > 1) { context.setState(new StateLowerCase()); } }}
StateContext.class
class StateContext { private Statelike myState; StateContext() { setState(new StateLowerCase()); } /** * Setter method for the state. * Normally only called by classes implementing the State interface. * @param newState the new state of this context */ void setState(final Statelike newState) { myState = newState; } public void writeName(final String name) { myState.writeName(this, name); } public static void main(String[] args) { final StateContext sc = new StateContext(); sc.writeName("Monday"); sc.writeName("Tuesday"); sc.writeName("Wednesday"); sc.writeName("Thursday"); sc.writeName("Friday"); sc.writeName("Saturday"); sc.writeName("Sunday"); }}
最后结果:
mondayTUESDAYWEDNESDAYthursdayFRIDAYSATURDAYsunday
例子也很简单,一目了然。
总结
状态模式的关键点在于不同的状态下对于统一行为有不同的响应,这其实就是一个将 if-else 用多态来实现的一个具体实例。在 if-else 或者 switch-case 形势下根据不同的状态进行判断,如果是状态 A 那么执行方法 A,状态 B 执行方法 B,但这种实现使得逻辑耦合在一起,易于出错不易维护,通过状态模式能够很好的消除这类“丑陋”的逻辑处理,当然并不是任何出现 if-else 的地方都应该通过状态模式重构,模式的运用一定要考虑所处的情景以及你要解决的问题,只有符合特定的场景才建议使用对应的模式。和程序状态机(PSM)不同,状态模式用类代表状态,状态的转换可以由 State 类或者 Context 类控制。
优点:
- 通过将每个状态封装进一个类,将以后所做的修改局部化;
- 将所有与一个特定状态相关的行为封装到一个对象中,繁琐的状态判断转换成结构清晰的状态类族,在避免代码膨胀的同时增加可维护性和可扩展性。
源码下载
https://github.com/zhaozepeng/Design-Patterns/tree/master/StatePattern
引用
https://en.wikipedia.org/wiki/State_pattern
http://blog.csdn.net/jason0539/article/details/45021055
http://blog.csdn.net/shulianghan/article/details/38487967
http://blog.csdn.net/eager7/article/details/8517827
- java/android 设计模式学习笔记(19)---状态模式
- Android设计模式学习笔记(状态模式)
- Java/Android 设计模式系列(19)--状态模式
- 学习笔记——JAVA设计模式<20>状态模式
- java/android 设计模式学习笔记(2)---观察者模式
- java/android 设计模式学习笔记(6)---适配器模式
- java/android 设计模式学习笔记(9)---代理模式
- java/android 设计模式学习笔记(11)---原型模式
- java/android 设计模式学习笔记(12)---组合模式
- java/android 设计模式学习笔记(14)---外观模式
- java/android 设计模式学习笔记(16)---命令模式
- java/android 设计模式学习笔记(17)---策略模式
- java/android 设计模式学习笔记(20)---迭代器模式
- java/android 设计模式学习笔记(21)---备忘录模式
- java/android 设计模式学习笔记(9)---代理模式
- java/android 设计模式学习笔记(24)---访问者模式
- 设计模式学习笔记-状态模式
- 设计模式学习笔记(状态模式)
- Java基础方法的初使用规则
- poj 1486 网络流+tarjan
- zigzag数组的C语言实现
- js中typeof的用法
- 主键约束与唯一性约束的区别
- java/android 设计模式学习笔记(19)---状态模式
- CSU 1811 Tree Intersection
- 用网络线程编写的石头剪刀布
- <boost-05> boost::filesystem 常用命令集合
- TQ210——按键(中断查询法)
- Http协议学习
- 2235 机票打折
- java保留两位小数
- 台风仿佛他飓风