posts - 262,  comments - 221,  trackbacks - 0
注:本文多处引用了WWW.jdon.com网站的《State模式》一文,原文前参见:http://www.jdon.com/designpatterns/designpattern_State.htm

一、State模式定义:

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

二、State模式的适用场合:

State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If elseif else 进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了.

三、State模式与Command模式的比较:

前者从调用者和被调用者的角度出发,目的是封装被调用者的行为,让调用者只和统一的顶层接口打交道。后者从对象自身的状态出发,不涉及调用者和被调用者。是对象自身的状态切换导致的行为变化。

四、“开关切换状态” 和“ 一般的状态判断”区别:

“开关状态切换”经常发生在GUI界面的交互过程中,通过结合对象当前状态和参数,判断接下来对象应该切换到什么状态。被判断对象和被更新对象都是同一个。这一点和“一般的状态判断”是不同的,后者是根据其它对象或属性的值来更新自身的状态。被判断对象和被更新对象不是同一个。

例如:if (which==1) state="hello";
   else if (which==2) state="hi";
   else if (which==3) state="bye";

这是一个 " 一般的状态判断",state值的不同是根据which变量来决定的,which和state没有关系.如果改成:

if (state.euqals("bye")) state="hello";
else if (state.euqals("hello")) state="hi";
else if (state.euqals("hi")) state="bye";

这就是 "开关切换状态",是将state的状态从"hello"切换到"hi",再切换到""bye";再切换到"hello",好象一个旋转开关,这种状态改变就可以使用State模式了.

五、State模式的构成:

1.state manager 状态管理器,就是开关,如上面例子的Context实际就是一个state manager, 在state manager中有对状态的切换动作.

2.用抽象类或接口实现的父类,,不同状态就是继承这个父类的不同子类(也就是不同的状态行为)

六、State模式的例子:

状态机--父类定义

public abstract class State// 状态行为的父类

      
// 状态机需要能够感知上下文的情况,也就是之前的状态和目前的情形,所以用Context作为参数
     public abstract void handlepush(Context c);
  public abstract void handlepull(Context c);
  public abstract void getcolor();

}

状态机--子类实现
public class BlueState extends State{

  
public void handlepush(Context c){
     
//根据push方法"如果是blue状态的切换到green" ;
     c.setState(new GreenState());

  }


  
public void handlepull(Context c){
            
//根据pull方法"如果是blue状态的切换到red" ;
    c.setState(new RedState());
      }


  
public abstract void getcolor()return (Color.blue)}

}

特点:

·拥有一个父类,表示各种不同的状态。该父类具有三个典型的方法:
    ·切换到上一个状态
    ·切换到下一个状态
    ·获取当前状态
·拥有一至多个子类,在子类中实现具体的状态向前、向后的切换
·如果把每个状态看成一个“状态链”上的一个独立的节点,那么有N个状态,则需要N个子类。
·如果状态只支持单向切换,则除了首尾两个状态,其它状态的节点均有两个方法,分别是向前/后一个状态的切换
·如果状态支持双向切换(例如MP3的自动循环播放功能),则尾节点可以有两个状态切换的方法


状态机管理器
public class Context{

  
private Sate state=null; //我们将原来的 Color state 改成了新建的State state;

  
//setState是用来改变state的状态 使用setState实现状态的切换,不同的状态传入不同的State,都是State的子类
  pulic void setState(State state){
    
this.state=state;
      }


  
public void push(){
            
//状态的切换的细节部分,在本例中是颜色的变化,已经封装在子类的handlepush中实现,这里无需关心
    state.handlepush(this);
    
    
//因为sample要使用state中的一个切换结果,使用getColor()
    Sample sample=new Sample(state.getColor());
    sample.operate(); 
      }


  
public void pull(){
          state.handlepull(this);

    Sample2 sample2
=new Sample2(state.getColor());
    sample2.operate(); 

  }


}

特点:

·拥有一个状态机对象:用于代表当前的状态
·拥有一个切换到上/下一个状态的方法:实际上是调用了状态机自身的切换方法,由于状态机本身已经“知道”自己是什么状态,所以可以方便的切换到上、下一个状态。例如:state.handlePush(this)这个方法,由于此时state对象是什么类型已经知道(通过对管理器中的状态机赋值),所以切换工作就交给了对象本身了,调用者不需要知道内部是如何切换的。
·拥有一个获取当前状态的方法

我们可以看到,在状态机的上下文中,push和pull方法都把上下文本身作为参数传递给状态机,然后在状态机中调用了上下文的setState(Context c)方法。这是一个典型的Call-back(回调)机制。


七、状态机模式的优点:

(1) 封装转换过程,也就是转换规则
(2) 枚举可能的状态,因此,需要事先确定状态种类。

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

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

十、状态模式和其它模式的结合应用:

从状态模式的实质:“只关心它的下一个可能状态”和客户端使用特点:“使用事件Event实现”来看,我们可以考虑将观察者模式(Observer)和状态模式(State)结合起来。被观察者在改变时发送广播消息(Event事件),观察着注意并接收该消息后,使用状态机来对当前应用的上下文进行状态的切换。



-------------------------------------------------------------
生活就像打牌,不是要抓一手好牌,而是要尽力打好一手烂牌。
posted on 2008-04-07 18:02 Paul Lin 阅读(7041) 评论(2)  编辑  收藏 所属分类: 模式与重构


FeedBack:
# re: 设计模式总结-State模式
2011-11-28 10:45 | joyjjjz
很好,谢谢!  回复  更多评论
  
# re: 设计模式总结-State模式[未登录]
2012-08-28 22:11 | james
good  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
<2008年4月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

常用链接

留言簿(19)

随笔分类

随笔档案

BlogJava热点博客

好友博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜