浅学设计模式之状态<state>模式

State模式定义:

      不同的状态,不同的行为; 或者说,每个状态有着相应的行为.

使用情况:

        状态模式在工作流或游戏等各种系统中有大量使用,甚至是这些系统的核心功能设计,例如在典型的OA中,一个批文的状态有多种:未办;正在办理;正在批示;正在审核;已经完成等各种状态,使用状态机可以封装这个状态的变化规则,从而达到扩充状态时,不必涉及到状态的使用者。

       在网游中,一个游戏活动存在开始、开玩、正在玩、输赢等状态,使用状态模式就可以实现游戏状态的总控,而游戏状态决定了游戏的各个方面,使用状态模式可以对整个游戏架构功能实现起到决定的主导作用。


        状态模式可以有效的替换充满在程序中的if else语句:将不同条件下的行为封装在一个类里面,再给这些类一个统一的父类来约束他们。看一下状态模式的角色组成:

  1. 使用环境(Context)角色:客户程序是通过它来满足自己的需求。它定义了客户程序需要的接口;并且维护一个具体状态角色的实例,这个实例来决定当前的状态。 
  2. 状态(State)角色:定义一个接口以封装与使用环境角色的一个特定状态相关的行为。
  3. 具体状态(Concrete State)角色:实现状态角色定义的接口。

之间的协作关系:

  1.  Context将于状态相关的请求委托给当前的ConcreteState对象处理。
  2.  Context可将自身作为一个参数传递给处理该请求的状态对象,这使得状态对象在必要的时候可访问Context
  3.  Context是客户使用的主要接口,客户可用状态对象来配置一个Context,一旦一个Context配置完毕,他的客户不再需要直接与状态对象打交道。
  4. Context或者ConcreteState子类都可以决定哪个状态是另外那个状态的后继者,以及是在何种条件下进行状态转换。



状态模式实质

使用状态模式前,客户端外界需要介入改变状态,而状态改变的实现是琐碎或复杂的。

使用状态模式后,客户端外界可以直接使用事件Event实现,根本不必关心该事件导致如何状态变化,这些是由状态机等内部实现。

这是一种Event-condition-State,状态模式封装了condition-State部分。

每个状态形成一个子类,每个状态只关心它的下一个可能状态,从而无形中形成了状态转换的规则。如果新的状态加入,只涉及它的前一个状态修改和定义。

状态转换有几个方法实现:一个在每个状态实现next(),指定下一个状态;还有一种方法,设定一个StateOwner,在StateOwner设定stateEnter状态进入和stateExit状态退出行为。

状态从一个方面说明了流程,流程是随时间而改变,状态是截取流程某个时间片。



适用场合:

       (1)

        State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If elseif else 进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了. 适合于内部状态,不断循环变化的.
     (2)
一个state,包括两部分: 对象 + 对象内部的属性(属性接口+具体属性)
一个对象,要有其属性,以及其setter,getter.且设置好其初始状态+一个调用显示状态的方法(里面就是状态调用自身的显示方法).
一个属性接口,应该有一个执行的方法.
一个具体属性,须包含对象进去,实现方法中,须设置对象下一个要显示的属性-->从而在对象下次调用方法时,其属性值会变化.


代码例子:

该代码使用电梯作为模板设置了四种状态

       State接口:

  1. public interface IState {  
  2.     void open();  
  3.     void close();  
  4.     void runing();  
  5.     void stop();  
  6. }  

具体角色(Concrete State)

  1. public class OpenState implements IState {  
  2.     private Lift lift;  
  3.       
  4.     public OpenState(Lift lift){  
  5.         this.lift = lift;  
  6.     }  
  7.   
  8.     @Override  
  9.     public void open() {  
  10.         // TODO Auto-generated method stub  
  11.         System.out.println("门已经开了!!!");  
  12.     }  
  13.   
  14.     @Override  
  15.     public void close() {  
  16.         // TODO Auto-generated method stub  
  17.         System.out.println("好的,现在关门");  
  18.         lift.setState(lift.getCloseState());  
  19.     }  
  20.   
  21.     @Override  
  22.     public void runing() {  
  23.         // TODO Auto-generated method stub  
  24.         System.out.println("现在门开着,电梯没办法运行");  
  25.     }  
  26.   
  27.     @Override  
  28.     public void stop() {  
  29.         // TODO Auto-generated method stub  
  30.         System.out.println("现在门开着,电梯是停止状态");  
  31.     }  
  32.   
  33. }  

  1. ublic class RunState implements IState {  
  2.     private Lift lift;  
  3.       
  4.     public RunState(Lift lift){  
  5.         this.lift = lift;  
  6.     }  
  7.   
  8.     @Override  
  9.     public void open() {  
  10.         // TODO Auto-generated method stub  
  11.         System.out.println("现在正在运行,没办法开门");  
  12.     }  
  13.   
  14.     @Override  
  15.     public void close() {  
  16.         // TODO Auto-generated method stub  
  17.         System.out.println("现在是运行状态,门已经关闭");  
  18.     }  
  19.   
  20.     @Override  
  21.     public void runing() {  
  22.         // TODO Auto-generated method stub  
  23.         System.out.println("电梯正在运行中....");  
  24.     }  
  25.   
  26.     @Override  
  27.     public void stop() {  
  28.         // TODO Auto-generated method stub  
  29.         System.out.println("让电梯停止");  
  30.         lift.setState(lift.getStopState());  
  31.     }  
  32.   
  33. }  

  1. public class StopState implements IState {  
  2.     private Lift lift;  
  3.     public StopState(Lift lift){  
  4.         this.lift = lift;  
  5.     }  
  6.   
  7.     @Override  
  8.     public void open() {  
  9.         // TODO Auto-generated method stub  
  10.         System.out.println("现在打开电梯");  
  11.         lift.setState(lift.getOpenState());  
  12.     }  
  13.   
  14.     @Override  
  15.     public void close() {  
  16.         // TODO Auto-generated method stub  
  17.         System.out.println("电梯现在关闭");  
  18.         lift.setState(lift.getStopState());  
  19.     }  
  20.   
  21.     @Override  
  22.     public void runing() {  
  23.         // TODO Auto-generated method stub  
  24.         System.out.println("好吧,让电梯开始运行");  
  25.         lift.setState(lift.getRunState());  
  26.     }  
  27.   
  28.     @Override  
  29.     public void stop() {  
  30.         // TODO Auto-generated method stub  
  31.         System.out.println("现在正是在停止状态");  
  32.     }  
  33.   
  34. }  

  1. public class CloseState implements IState {  
  2.     private Lift lift;  
  3.       
  4.     public CloseState(Lift lift){  
  5.         this.lift = lift;  
  6.     }  
  7.   
  8.     @Override  
  9.     public void open() {  
  10.         // TODO Auto-generated method stub  
  11.         System.out.println("正要准备打开门");  
  12.         lift.setState(lift.getOpenState());  
  13.     }  
  14.   
  15.     @Override  
  16.     public void close() {  
  17.         // TODO Auto-generated method stub  
  18.         System.out.println("现在门正在关着");  
  19.     }  
  20.   
  21.     @Override  
  22.     public void runing() {  
  23.         // TODO Auto-generated method stub  
  24.         System.out.println("现在让电梯运行");  
  25.         lift.setState(lift.getRunState());  
  26.     }  
  27.   
  28.     @Override  
  29.     public void stop() {  
  30.         // TODO Auto-generated method stub  
  31.         System.out.println("现在让电梯停止");  
  32.         lift.setState(lift.getStopState());  
  33.     }  
  34.   
  35. }  

context类:
  1. public class Lift {  
  2.     private IState openState;  
  3.     private IState closeState;  
  4.     private IState runState;  
  5.     private IState stopState;  
  6.       
  7.     private IState state ;  
  8.       
  9.     public Lift(){  
  10.         openState = new OpenState(this);  
  11.         closeState = new CloseState(this);  
  12.         runState = new RunState(this);  
  13.         stopState = new StopState(this);  
  14.         state = stopState;  
  15.     }  
  16.       
  17.     public void openLift(){  
  18.         state.open();  
  19.     }  
  20.       
  21.     public void runLift(){  
  22.         state.runing();  
  23.     }  
  24.       
  25.     public void stopLift(){  
  26.         state.stop();  
  27.     }  
  28.       
  29.     public void closeLift(){  
  30.         state.close();  
  31.     }  
  32.       
  33.     public void setState(IState state){  
  34.         this.state = state;  
  35.     }  
  36.       
  37.       
  38.     public IState getOpenState() {  
  39.         return openState;  
  40.     }  
  41.     public IState getCloseState() {  
  42.         return closeState;  
  43.     }  
  44.     public IState getRunState() {  
  45.         return runState;  
  46.     }  
  47.     public IState getStopState() {  
  48.         return stopState;  
  49.     }  
  50.       
  51. }  

测试类:
  1. public class Test {  
  2.     public static void main(String[] args){  
  3.         Lift lift = new Lift();  
  4.         //好,现在打开电梯门进去  
  5.         lift.openLift();  
  6.         //关闭电梯门  
  7.         lift.closeLift();  
  8.         //让电梯开始运行  
  9.         lift.runLift();  
  10.         //电梯到了,停止  
  11.         lift.stopLift();  
  12.         //打开电梯门  
  13.         lift.openLift();  
  14.           
  15.         //现在一个小朋友乱按电梯  
  16.         Lift lift2 = new Lift();  
  17.         //好,现在打开电梯门进去  
  18.         lift2.openLift();  
  19.         //又按了次开门  
  20.         lift2.openLift();  
  21.         //开门状态下,让电梯运行  
  22.         lift2.runLift();  
  23.         //好吧,不玩了,关闭电梯门  
  24.         lift2.closeLift();  
  25.         //让电梯开始运行  
  26.         lift2.runLift();  
  27.         //在运行过程中想打开门  
  28.         lift2.openLift();  
  29.         //电梯到了,停止  
  30.         lift2.stopLift();  
  31.         //打开电梯门  
  32.         lift2.openLift();  
  33.     }  
  34. }  

测试结果:
  1. 现在打开电梯  
  2. 好的,现在关门  
  3. 现在让电梯运行  
  4. 让电梯停止  
  5. 现在打开电梯  
  6. ---------  
  7. 现在打开电梯  
  8. 门已经开了!!!  
  9. 现在门开着,电梯没办法运行  
  10. 好的,现在关门  
  11. 现在让电梯运行  
  12. 现在正在运行,没办法开门  
  13. 让电梯停止  
  14. 现在打开电梯  





状态模式与观察者模式的区别:
状态模式,也跟观察者模式一样,是一对多的模式。但观察者模式是“一”变了,所有的“多”也会更新。
状态模式,强调的是:“多”是“一”的各个状态,“一”的各个状态,进行不断的循环。
 
如何建立一与多的关系:
        “多”,都是实现一个接口的。所以,在“一”的类中,声明的是“多”的接口;若“多”中要建立与“一”的关系,只须直接在类中声明“一”即可。



状态模式与其他模式的区别:
  1. 状态模式,也跟观察者模式一样,是一对多的模式。但观察者模式是“一”变了,所有的“多”也会更新。状态模式,强调的是:“多”是“一”的各个状态,“一”的各个状态,进行不断的循环。
  2. 状态模式的主要使用方法,是作为实例变量,通过set属性方法,或者构造器把状态接口的具体实现类的实例传递进来
  3. 通常命令模式的接口中只有一个方法。而状态模式的接口中有1个或者多个方法。命令模式的主要的使用方式是参数回调模式。命令接口作为方法的参数传递进来。然后,在方法体内回调该接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值