关于state模式的理解
如下边wikipedia的例子,State模式中state的子类可以互相切换。我觉得这种设计子类之间需要相互知道,耦合性很高。为什么不考虑让StateContext来维护state子类间切换?
它可以跟据针对state类的调用情况(例如返回值),来切换子类。这样降低了子类之间的耦合性,而且如果增加新的state,修改StateContext就可以了,不用在修改其他跟新state可以切换的旧state.
---------------------------------------
The state interface and two implementations. The state method has a reference to the context object and is able to change its state.
interface State {
public void writeName(StateContext stateContext, String name);
}
class StateA implements State {
public void writeName(StateContext stateContext, String name) {
System.out.println(name.toLowerCase());
stateContext.setState(new StateB());
}
}
class StateB implements State {
private int count=0;
public void writeName(StateContext stateContext, String name){
System.out.println(name.toUpperCase());
// change state after StateB's writeName() gets invoked twice
if(++count>1) {
stateContext.setState(new StateA());
}
}
}
The context class has a state variable which it instantiates in an initial state, in this case StateA. In its method, it uses the corresponding methods of the state object.
public class StateContext {
private State myState;
public StateContext() {
setState(new StateA());
}
// normally only called by classes implementing the State interface
public void setState(State newState) {
this.myState = newState;
}
public void writeName(String name) {
this.myState.writeName(this, name);
}
}
--------------------------------------------------------------
http://en.wikipedia.org/wiki/State_pattern
------解决方案--------------------这个例子给的很简单,当然想你说的一样可以直接传值给StateContext,让StateContext来进行各种Switch。而且那么做代码看起来更漂亮。不过,我只说这样做的坏处。
像Wiki这么做,代码更加好查阅?直接可以从new StateA就杀进去看StateA的构造函数了,省着还要自己去查找Switch/Case。
当State少的时候,用Switch/Case来统一管理是很漂亮的,当State多的时候,那就要权衡了,因为你每次都是在修改总开关,反复编译它,也容易造成ディグレート(《-这玩意叫啥来着,忘记了。。。就是把好的地方也改坏了)但是你把总开关分散到子类里面以后,这风险就减少不少,至少不会造成全局的风险。
其实解耦合这种事情有利有弊,如果是我大学时代我会义无反顾支持解耦合,
但是现在就未必。。毕竟解耦合过度可能造成class的力度过细,这就是个平衡问题。
和设计模式相比,平衡更加的重要。适合项目的设计才是更加重要的。
------解决方案--------------------gof的书上还介绍了另一个方法:表驱法。
如果后继状态明确,让state自己指定,逻辑明了代码简单挺好的。还有在前级后继依赖程度高外加有附属动作时,表驱动不方便,不如代码耦合。这些都需要视情况确定。扩展新的state,不需要修改旧的state。
《敏捷软件开发、...》上还提到使用大叔的smc来生成代码(generation gap模式)。