主题:谈谈Strategy和State

今天想谈谈Strategy和State这两个模式,这两个模式很相似,记得以前上网找关于这两个模式的资料,看的多了,讲的好的也有,但是讲的不清不楚的也很多,到最后能把人说的认为这两个模式没什么区别。     

  今天想就两个例子来说明一下这两个模式。 其实这两个模式的结构都非常相似,一个接口或者抽象类,代表着策略抽象和状态抽象,然后有一些实现或者继承类,接着会有个环境类,里面都会有一个接口或者抽象类同类型的数据成员,客户程序都是用这个环境类去操作,去调用具体实现类中的方法。

那么它们究竟有什么区别,GOF不可能就把一样的模式分成两种模式来定义,我就我的理解来说说究竟有什么不同。

从使用的动机来说,就是为什么会用Strategy,为什么又会用State模式.

在我们平时的开发时,会遇到这样的问题,当我们业务实现有很多种方法实现时,我们需要利用面向对象的多态性质,去完成我们的任务,多态之间相互独立,每一个都可以完成我们的业务需求,只是实现的具体方法不同,我们可以认为到达的目的地都是一样,只是路线和行进方式的不同,然后我们要根据具体的环境来决定我们要怎么去做,怎么达到目的,对于客户程序来说,它的关注焦点在于我现在决定我要怎么去,而你带我去就可以了,其他的它不关心。而一旦确定,具体实现类中会帮助我们完成,而至于他完成不完成并不依赖于我们的环境类,你既然确定了具体到达目的地的途径,那么就不会改变了,这样的情况我们就可以使用 strategy模式,打个比方吧:我们要做加减乘除运算,它们的接口是运算,而具体实现类就是加类,减类,乘类,除类,你在环境类中一旦说我要做除法,ok,我就去执行除法。

那么你可能会说state模式又有什么用,在我们的实际开发中,经常会根据一些状态去决定我究竟要干嘛,会用一些条件分支或者开关语句,这个没有问题,关键的问题在,我们一旦决定了分支以后我们要做什么,如果我们可以把加减乘除四个状态做成一个分支,那么每个分支里去做的事情就是加减乘除的实际操作,那么试问,这样和策略模式又有什么不同,至少我看不出有什么不同,所以我认为,关键的地方就在于如果进入一个确定的状态分支后,我们又要对这个状态进行转换,那么这样就符合了使用state模式的条件了:

if(state ==1){
    state=2;
    do...
}else if(state =2){
    state=3
    do...
}else if(...){
    ...
}...

  再来打个比方,现实生活中的红绿信号控制灯,我想大家都知道吧,它有红,黄,绿三个状态,转换方式为:红-->黄-->绿-->黄-->红  

那么这个时候具体的实现类在每次执行完自己的事情后东都去要多干一件事,去改变相应的状态,这个时候我们完全就可以把状态这个东西给抽象出来,而在Strategy模式中根本没有状态这个概念,它只是单纯的实现具体算法和接口以及调用之间的接耦,而state模式中,状态是核心的概念。来看看我写的一段测试代码:(只是为了方便理解,但是会有一些问题,我稍后会说)            

public interface State {
public void changeState(Context cxt);

public void doItself(Context cxt);

public String getNowState();

}

package cs.john.state;

public class RedState implements State {

public String getNowState(){
return "Red";
}

public void changeState(Context cxt) {;
cxt.setPreColor("Red");
State s = new YellowState();
    cxt.setState(s);
}

public void doItself(Context cxt) {
        System.out.println(cxt.getState().getNowState());
}
}
package cs.john.state;

public class YellowState implements State {

public String getNowState(){
return "Yellow";
}

public void changeState(Context cxt) {
String prestate = cxt.getPreColor();
State s = prestate.equals("Red")?new GreenState():new RedState();
cxt.setState(s);
}

public void doItself(Context cxt) {
System.out.println(cxt.getState().getNowState());

}
}
package cs.john.state;

public class GreenState implements State {

public String getNowState(){
return "Green";
}

public void changeState(Context cxt) {
cxt.setPreColor("Green");
State s = new YellowState();
cxt.setState(s);
}

public void doItself(Context cxt) {
        System.out.println(cxt.getState().getNowState());
}

}




很简单,我定义了一个State接口,这个接口代表状态,所以它有三个实现,既红 绿 黄三种,那么这个接口要做什么事情,我认为,主要是做两件事情,第一,做当状态在红 绿 黄时该做的事情,第二,改变状态,比如:红色的下个状态是黄色,还要,有个辅助的方法,告诉外界现在是在哪个状态下,请注意,在前面两个方法中的参数是传递一个环境类的实例进来,很奇怪,为什么要这个参数,而且看看我们的具体实现类中,发现在改变状态的时候,其实是在改变这个环境类对象中的状态数据成员,换句话说,就是状态是动态改变的。下面看看那个环境类吧:

package cs.john.state;

public class Context {

private State state;

private String preColor;

private int count;

public int getCount(){
return this.count;
}

public void setCount(int count){
this.count = count;
}


public String getPreColor() {
return preColor;
}

public void setPreColor(String preColor) {
this.preColor = preColor;
}

public Context(State state){
this.state = state;
}

public State getState(){
return this.state;
}

public void setState(State state){
this.state = state;
}

public void doAction(){
this.state.doItself(this);
this.state.changeState(this);
}

public static void main(String[]args){
State rs = new RedState();
Context cxt = new Context(rs);
int count = cxt.getCount();
while(count<5){
    cxt.doAction();
    count++;
}
}

}




现在应该很清楚了,state模式和strategy模式的关键区别也就在这里,每个实现类中要去维护环境类中的状态实例,其实这个状态实例就是实现类需要去实现的那个接口类型,方法doAction做了两件事情,调用了具体状态实现类的接口方法,这就体现了状态的改变,而且是因为状态的改变导致了状态的再次改变,但是我说有一些问题,现在就要说了,这个例子中大家有没有注意黄灯,它的状态的改变是不定的,也就是说他的状态改变是需要看环境对象中的状态成员的,所以我定义了一个preState数据成员,在红变黄时给它赋值,表示这个黄灯是从红灯变过去的,绿灯也同理,其实这又是个state问题了,所以问题出现了,如果一个状态的改变不依赖于唯一的条件,那怎么办,比如黄灯的改变会有N多种先决条件,那怎么办?所以我说这里会有一些问题,也许是例子本来就有问题,但是我想还是能说明问题的,所以我想说的是,最好能确定下一状态,而不要以又搞出不同的状态去决定下一个状态,这样就比较复杂了。也不知道我说的对不对。只是自己的一些理解和观点,也希望大家的指正和交流。

posted @ 2011-11-24 16:00  Flying Dreams  阅读(182)  评论(0编辑  收藏  举报