被说了很多遍的设计模式---状态模式
来源:互联网 发布:mcrypt php 扩展 编辑:程序博客网 时间:2024/05/02 03:06
[把你的理性思维慢慢变成条件反射]
本文,我们讲介绍抽象工厂模式,文章主题结构与上文一致。惯例,先来看看我们示例工程的环境:
操作系统:win7 x64
其他软件:eclipse mars,jdk7
-------------------------------------------------------------------------------------------------------------------------------------
经典问题:
状态转化。(在电商系统中,订单,物流,库存等功能中尤为常见)思路分析:
要点一:对相同的对象存在多个可以相互转化的状态。
要点二:不同状态表达不同的行为,业务含义。
示例工程:
错误写法:
创建StateChanged.java文件,具体内容如下:package com.yonyou.iuap.gof_State;public class StateChanged {public static int Condition = 0;public static boolean IsDone = false;public static void StateChanged() {if (Condition < 10) {System.out.println("Condition < 10");} else if (10 < Condition && Condition < 20) {System.out.println("10 <Condition< 20");} else if (20 < Condition && Condition < 30) {System.out.println("20 <Condition< 30");} else {if (IsDone) {System.out.println("Is Done");} else {System.out.println("Not Done");}}}}创建Window.java文件,具体内容如下:
package com.yonyou.iuap.gof_State;public class Window {public static void main(String[] args) {StateChanged.Condition = 1;StateChanged.StateChanged();StateChanged.Condition = 12;StateChanged.StateChanged();StateChanged.Condition = 13;StateChanged.StateChanged();StateChanged.Condition = 14;StateChanged.StateChanged();StateChanged.IsDone = true;StateChanged.Condition = 21;StateChanged.StateChanged();}}
错误原因:
状态转换由“if...else...”完成,类似的实现缺点在前文中已经反复说明:过程性的代码应用在面向对象的程序中,后期会无形中增加维护与扩展性,即违反了诸多的原则。同时,对于内部成员变量,设计实现为公有的,也是一种不合适的实现。
推荐写法:
创建Condition.java文件,具体内容如下:
package com.yonyou.iuap.gof_State.two;public class Condition {public int Condition = 0;public boolean IsDone = false;public State state;public Condition(){this.state = new ConcreteState10();}public State getState() {return state;}public void setState(State state) {this.state = state;}public int getCondition() {return Condition;}public void setCondition(int condition) {Condition = condition;}public boolean isIsDone() {return IsDone;}public void setIsDone(boolean isDone) {IsDone = isDone;}public void conditionChanged() {this.state.stateChanged(this);}}创建State.java文件,具体内容如下:
package com.yonyou.iuap.gof_State.two;public abstract class State {public abstract void stateChanged(Condition context);}创建ConcreteState10.java,ConcreteState20.java,ConcreteState30.java,ConcreteState40.java文件,具体内容如下:
package com.yonyou.iuap.gof_State.two;public class ConcreteState10 extends State{@Overridepublic void stateChanged(Condition condition) {if(condition.getCondition()<10){System.out.println("Condition()<10");}else{condition.setState(new ConcreteState20());condition.conditionChanged();}}}创建ConcreteState50.java文件,具体内容如下:
package com.yonyou.iuap.gof_State.two;public class ConcreteState50 extends State {@Overridepublic void stateChanged(Condition condition) {if(condition.IsDone){System.out.println("Is Done");}else{System.out.println("Not Done");}}}创建Window.java文件,具体内容如下:
package com.yonyou.iuap.gof_State.two;public class Window {public static void main(String[] args) {Condition condition = new Condition();System.out.println("Condition(1)-----------");condition.setCondition(1);condition.conditionChanged();System.out.println("Condition(12)----------");condition.setCondition(12);condition.conditionChanged();System.out.println("Condition(13)----------");condition.setCondition(13);condition.conditionChanged();System.out.println("Condition(14)----------");condition.setCondition(14);condition.conditionChanged();System.out.println("IsDone(true)-----------");System.out.println("Condition(21)----------");condition.setIsDone(true);condition.setCondition(21);condition.conditionChanged();System.out.println("IsDone(false)----------");System.out.println("Condition(22)----------");condition.setIsDone(false);condition.setCondition(22);condition.conditionChanged();}}
推荐原因:
每一个状态都进行了职责分离,极大的方便了后续的维护性,扩展性。代码含义一目了然,减少了各个功能之间的耦合程度。模式总结:
标准状态模式UML结构图:
状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。(主要功能是:当控制一个对象状态转换的条件表达式过于复杂是,把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。)
组成部分:Context(上下文环境类),State(抽象状态类),ConcreteState(具体状态类)三个组成部分。
模板代码:
创建Context.java文件,具体内容如下:
package com.yonyou.iuap.gof_State.one;public class Context {private State state;public Context(State state){this.state = state;}public State getState() {return state;}public void setState(State state) {this.state = state;System.out.println(state.getClass().getName());}public void request(){state.Handle(this);}}创建State.java文件,具体内容如下:
package com.yonyou.iuap.gof_State.one;public abstract class State {public abstract void Handle(Context context);}创建ConcreteStateA.java文件,具体内容如下:
package com.yonyou.iuap.gof_State.one;public class ConcreteStateA extends State{@Overridepublic void Handle(Context context) {context.setState(new ConcreteStateB());}}创建Window.java文件,具体内容如下:
public class Window {public static void main(String[] args) {Context c = new Context(new ConcreteStateA());c.request();}}
反思:
首先,需要说明的是:上面的代码,我们仅仅是作为示例。在实际应用时,上下文Context类中可以扩充具有实际意义的成员变量。第二,状态需要有一个初始值,如果客户端未设定,那么程序中需要明确指明。第三,状态转化的具体实现位置:在示例中,我们是在具体状态类中实现切换,而实际上,也可以在上下文环境类中,进行统一的切换,具体时间步骤就是通过if...else...实现,当然,这种实现方法,在较少的具体子类中可以应用,并且,通过介绍该模式,这种方式也是不推荐给大家的。
应用场景:
- 对象的行为严格依赖于他的状态,属性等。
- 对象的行为存在大量与状态有关的条件判断语句。
优点:
- 封装了状态的转化规则,转换的位置可以在上下文类,或者,具体子类中实现。
- 将所有的状态变化方法归属到一个上下文类当中,方便了后续的开发与维护。
- 避免了大量的条件判断语句块。
缺点:
- 如果存在大量的条件判断,应用该模式,必然会导致大量的类文件。
- 如果将状态转化实现在具体子类当中,可能会增加后续维护跟踪的工作量。
- 如果需要新增或删除,将需要修改相邻的状态对象。
-------------------------------------------------------------------------------------------------------------------------------------
至此,被说了很多遍的设计模式---状态模式 结束
参考资料:
图书:《大话设计模式》
其他博文:http://blog.csdn.NET/lovelion/article/details/7563445
- 被说了很多遍的设计模式---状态模式
- 被说了很多遍的设计模式---策略模式
- 被说了很多遍的设计模式---装饰模式
- 被说了很多遍的设计模式---代理模式
- 被说了很多遍的设计模式---原型模式
- 被说了很多遍的设计模式---外观模式
- 被说了很多遍的设计模式---观察者模式
- 被说了很多遍的设计模式---适配器模式
- 被说了很多遍的设计模式---备忘录模式
- 被说了很多遍的设计模式---组合模式
- 被说了很多遍的设计模式---迭代器模式
- 被说了很多遍的设计模式---命令模式
- 被说了很多遍的设计模式---访问者模式
- 被说了很多遍的设计模式---简单工厂模式
- 被说了很多遍的设计模式---工厂方法模式
- 被说了很多遍的设计模式---模板方法模式
- 被说了很多遍的设计模式---建造者模式
- 被说了很多遍的设计模式---抽象工厂模式
- 方块游戏 (银河英雄传说)(并查集)
- List的add方法剖析
- HDU1175
- Truck History
- PHP基础
- 被说了很多遍的设计模式---状态模式
- 【图论最短路】【CQBZOJ 1550】避开怪兽
- linux内核sysfs详解
- C# list存储的数据格式以及默认初始化空间,内存回收分析
- android-拼图小游戏
- pull方法解析XML文件
- Android观察者模式(Observable)实例
- Redis入门(五)有序集合Sorted SetSet
- Html5+JQuery页面标签的禁用问题