大话设计模式
字体: 16 + -

第169章

小a:“如何使用状态模式?”

大b:“状态模式可以允许客户端改变状态的转换行为,而状态机则是能够自动改变状态,状态机是一个比较独立的而且复杂的机制,具体可参考一个状态机开源项目:状态模式在工作流或游戏等各种系统中有大量使用,甚至是这些系统的核心功能设计,例如政府oa中,一个批文的状态有多种:未办;正在办理;正在批示;正在审核;已经完成等各种状态,使用状态机可以封装这个状态的变化规则,从而达到扩充状态时,不必涉及到状态的使用者。在网络游戏中,一个游戏活动存在开始;开玩;正在玩;输赢等各种状态,使用状态模式就可以实现游戏状态的总控,而游戏状态决定了游戏的各个方面,使用状态模式可以对整个游戏架构功能实现起到决定的主导作用。state需要两种类型实体参与:1、statemanager状态管理器,就是开关,如上面例子的context实际就是一个statemanager在statemanager中有对状态的切换动作。2、用抽象类或接口实现的父类,不同状态就是继承这个父类的不同子类。”

以上面的context为例。我们要修改它,建立两个类型的实体。

第一步:

首先建立一个父类:

publicabstractclassstate{

publicabstractvoidhandlepush(contextc);

publicabstractvoidhandlepull(contextc);

publicabstractvoidgetcolor();

}

父类中的方法要对应statemanager中的开关行为,在statemanager中这个例子就是context中,有两个开关动作push推和pull拉。那么在状态父类中就要有具体处理这两个动作:handlepush()handlepull();同时还需要一个获取push或pull结果的方法getcolor()。

下面是具体子类的实现:

publicclassbluestateextendsstate{

publicvoidhandlepush(contextc){

//根据push方法“如果是blue状态的切换到green”;

c.setstate(newgreenstate());

}

publicvoidhandlepull(contextc){

//根据pull方法“如果是blue状态的切换到red”;

c.setstate(newredstate());

}

publicabstractvoidgetcolor(){return(color.blue)}

}

同样其他状态的子类实现如blue一样。

第二步:

要重新改写statemanager也就是本例的context:

publicclasscontext{

privatesatestate=null;//我们将原来的colorstate改成了新建的statestate;

//setstate是用来改变state的状态使用setstate实现状态的切换

pulicvoidsetstate(statestate){

this.state=state;

}

publicvoidpush(){

//状态的切换的细节部分,在本例中是颜色的变化,已经封装在子类的handlepush中实现,这里无需关心

state.handlepush(this);

//因为sample要使用state中的一个切换结果,使用getcolor()

samplesample=newsample(state.getcolor());

sample.operate();

}

publicvoidpull(){

state.handlepull(this);

sample2sample2=newsample2(state.getcolor());

sample2.operate();

}

}

至此,我们也就实现了state的refactorying过程。

以上只是相当简单的一个实例,在实际应用中,handlepush或handelpull的处理是复杂的。