被说了很多遍的设计模式---状态模式

来源:互联网 发布: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...实现,当然,这种实现方法,在较少的具体子类中可以应用,并且,通过介绍该模式,这种方式也是不推荐给大家的。

应用场景:

  1. 对象的行为严格依赖于他的状态,属性等。
  2. 对象的行为存在大量与状态有关的条件判断语句。

优点:

  1. 封装了状态的转化规则,转换的位置可以在上下文类,或者,具体子类中实现。
  2. 将所有的状态变化方法归属到一个上下文类当中,方便了后续的开发与维护。
  3. 避免了大量的条件判断语句块。

缺点

  1. 如果存在大量的条件判断,应用该模式,必然会导致大量的类文件。
  2. 如果将状态转化实现在具体子类当中,可能会增加后续维护跟踪的工作量。
  3. 如果需要新增或删除,将需要修改相邻的状态对象。

-------------------------------------------------------------------------------------------------------------------------------------

至此,被说了很多遍的设计模式---状态模式 结束


参考资料:

图书:《大话设计模式》

其他博文:http://blog.csdn.NET/lovelion/article/details/7563445


0 0
原创粉丝点击