关于state模式的理解

qc123456 2011-03-10 09:24:58
如下边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
...全文
198 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
yuanhong2910 2011-03-11
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 cxyoooo 的回复:]

table-driven == 表驱(动)法,此处略去1个字。
gof的《设计模式》是必修课,得使劲看。
[/Quote]
我也觉得这个超级好……
积木 2011-03-10
  • 打赏
  • 举报
回复
这个例子给的很简单,当然想你说的一样可以直接传值给StateContext,让StateContext来进行各种Switch。而且那么做代码看起来更漂亮。不过,我只说这样做的坏处。

像Wiki这么做,代码更加好查阅?直接可以从new StateA就杀进去看StateA的构造函数了,省着还要自己去查找Switch/Case。

当State少的时候,用Switch/Case来统一管理是很漂亮的,当State多的时候,那就要权衡了,因为你每次都是在修改总开关,反复编译它,也容易造成ディグレート(《-这玩意叫啥来着,忘记了。。。就是把好的地方也改坏了)但是你把总开关分散到子类里面以后,这风险就减少不少,至少不会造成全局的风险。

其实解耦合这种事情有利有弊,如果是我大学时代我会义无反顾支持解耦合,
但是现在就未必。。毕竟解耦合过度可能造成class的力度过细,这就是个平衡问题。

和设计模式相比,平衡更加的重要。适合项目的设计才是更加重要的。
cxyOOOO 2011-03-10
  • 打赏
  • 举报
回复
table-driven == 表驱(动)法,此处略去1个字。
gof的《设计模式》是必修课,得使劲看。
pathuang68 2011-03-10
  • 打赏
  • 举报
回复
zhengjiankang 2011-03-10
  • 打赏
  • 举报
回复
没用过。不懂。
真不明白这些人是怎么想的。
命名就2个词。
抽象 and 封装。
才一大会的功夫。
搞出几十种设计模式
还让不让人活了啊。
很多模式
我怎么就看的他们也没多大差别呢
不都是那些几个原则么。

俺就不学那多的模式
俺就记着那几个原则就行了。
xiaoboalex 2011-03-10
  • 打赏
  • 举报
回复
其实仔细考虑一下state模式,会发现当状态很多的时候不是所有的状态子类之间都存在耦合关系,一个状态子类只和相关的几个状态子类存在耦合。 当新增一个状态的时候也只会影响相关的几个子类而已,这就像在链表中插入新的节点只会影响前驱和后继两个节点而已。

如果增加一个全局的控制类,首先这个类本身会很复杂,需要调度各个子类之间的切换;其次这个类又是和所有的子类耦合,修改,新增或删除任意一个子类都会对它产生影响; 而这个类也只是封装了原来客户端代码里面的复杂耦合关系而已。增加这样的全局控制类反而违背了state模式的本意,state模式就是利用几个子类之间有限的紧耦合来化解所有子类之间的耦合。
qc123456 2011-03-10
  • 打赏
  • 举报
回复
谢谢goodboy,按照你的理解,state比较多的情况下更适合使用标准state模式。

cxy0000,你说的表驱法指的是什么?百度不到。
cxyOOOO 2011-03-10
  • 打赏
  • 举报
回复
gof的书上还介绍了另一个方法:表驱法。

如果后继状态明确,让state自己指定,逻辑明了代码简单挺好的。还有在前级后继依赖程度高外加有附属动作时,表驱动不方便,不如代码耦合。这些都需要视情况确定。扩展新的state,不需要修改旧的state。

《敏捷软件开发、...》上还提到使用大叔的smc来生成代码(generation gap模式)。

5,530

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 模式及实现
社区管理员
  • 模式及实现社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧