在Java中应用State设计模式
用State模式改造
Door1类的代码比较复杂,整个类到处都用到了状态变量。如果要比较图1的状态机和Door1类的各个状态变换方法,将是非常困难的,click()方法尤其如此。那么,怎样在这个例子中应用State模式呢?首先要把传送门的各种状态分别定义成类,如图3所示。图3能够更好地与图1的状态机对应。更改后的类设计中,Door2包含了状态机的上下文信息。所谓上下文信息,就是描述环境和一系列其它对象相关的信息。就本例而言,State利用一个上下文对象记录了传送门的当前状态是DoorState类的哪一个实例。
public class Door2 extends Observable {
public final DoorState CLOSED = new DoorClosed(this);
// 按照类似方式定义DoorState类型的
// OPENING、OPEN、CLOSING、STAYOPEN对象(略)
private DoorState state = CLOSED;
// ...
}
DoorState类是一个抽象类,由子类实现其click()方法。在状态机中,每一个状态均有相应的“按下按钮”操作。修改后的设计中每一个描述状态的类也有一个click()方法,两者是一致的。DoorState类处理了其它可能的变换,所以DoorState的子类可以忽略无关的事件,代码如下:
public abstract class DoorState { 字串8
protected Door2 door;
public DoorState(Door2 door) {
this.door = door;
}
public abstract void click();
public String status() {
String s = getClass().getName();
return s.substring(s.lastIndexOf('.') + 1);
}
public void complete() { }
public void timeout() { }
}
由上可以看到,现在的status()方法要比修改设计方案之前的status()方法简单多了。新status()方法返回的结果与修改前版本的结果略有不同,它的状态信息从类的名称获得。如果要返回修改设计方案之前的信息,只需把这些状态信息分别记录到DoorState的各个子类中,然后在这个status()方法中直接提取即可。
新的设计方案中,传送门对象(Door2)从传送带接收状态改变信息的这一角色仍未改变。但现在Door2对象只需把这些状态改变信息直接传递给当前的状态对象就可以了,代码如下: 字串2
public class Door2 extends Observable {
// ... 声明变量
protected void setState(DoorState state) {
this.state = state;
setChanged();
notifyObservers();
}
public void click() {
state.click();
}
// complete()、status()、timeout()都直接
// 调用state的相应方法即可(略)
}
这里的click()、complete()、status()和timeout()方法体现了Java类多态性的应用。所有这些方法都起着判断和选择动作的作用,即是虽然每一个方法的代码是不含if判断逻辑的,但实际运行时被调用的状态对象却不断变化。在调用click()时会发生哪些事情呢?按照多态性规则,答案依赖于当时传送门的状态。修改后的代码有效地担负起了根据状态执行不同动作的任务,但由于利用了多态性,它变得更加简单了。
Door2类中的setState()方法现在由DoorState的子类调用。这些DoorState的子类与图1状态机中的相应实体很相似,例如,状态机中Open状态包含Timeout和Click,DoorOpen类则包含两个对应的方法timeout()和click()。DoorOpen类的代码如下:
public class DoorOpen extends DoorState {
public DoorOpen(Door2 door) {
super(door);
}
public void click() {
door.setState(door.STAYOPEN);
}
public void timeout() {
door.setState(door.CLOSING);
}
}
从上面可以看到,利用State设计模式之后,代码变得更简单了。不过,细心的读者或许已经注意到,Door2类用到的“常量”实际上是变量,这给人一种不规范的感觉。假设现在要把这些状态常量移到_DoorConstant接口,这就需要从DoorState类消除Door2实例变量。修改办法是:重新定义DoorState类中的click()、complete()和timeout()变换方法,把一个Door2对象以参数的形式传递给它们。按照这种设计方法,Door2对象调用状态变换方法,例如click()时,将采用state.click(this)的形式。
Door1类的代码比较复杂,整个类到处都用到了状态变量。如果要比较图1的状态机和Door1类的各个状态变换方法,将是非常困难的,click()方法尤其如此。那么,怎样在这个例子中应用State模式呢?首先要把传送门的各种状态分别定义成类,如图3所示。图3能够更好地与图1的状态机对应。更改后的类设计中,Door2包含了状态机的上下文信息。所谓上下文信息,就是描述环境和一系列其它对象相关的信息。就本例而言,State利用一个上下文对象记录了传送门的当前状态是DoorState类的哪一个实例。

图3 传送门各个状态 字串6
public class Door2 extends Observable {
public final DoorState CLOSED = new DoorClosed(this);
// 按照类似方式定义DoorState类型的
// OPENING、OPEN、CLOSING、STAYOPEN对象(略)
private DoorState state = CLOSED;
// ...
}
DoorState类是一个抽象类,由子类实现其click()方法。在状态机中,每一个状态均有相应的“按下按钮”操作。修改后的设计中每一个描述状态的类也有一个click()方法,两者是一致的。DoorState类处理了其它可能的变换,所以DoorState的子类可以忽略无关的事件,代码如下:
public abstract class DoorState { 字串8
protected Door2 door;
public DoorState(Door2 door) {
this.door = door;
}
public abstract void click();
public String status() {
String s = getClass().getName();
return s.substring(s.lastIndexOf('.') + 1);
}
public void complete() { }
public void timeout() { }
}
由上可以看到,现在的status()方法要比修改设计方案之前的status()方法简单多了。新status()方法返回的结果与修改前版本的结果略有不同,它的状态信息从类的名称获得。如果要返回修改设计方案之前的信息,只需把这些状态信息分别记录到DoorState的各个子类中,然后在这个status()方法中直接提取即可。
新的设计方案中,传送门对象(Door2)从传送带接收状态改变信息的这一角色仍未改变。但现在Door2对象只需把这些状态改变信息直接传递给当前的状态对象就可以了,代码如下: 字串2
public class Door2 extends Observable {
// ... 声明变量
protected void setState(DoorState state) {
this.state = state;
setChanged();
notifyObservers();
}
public void click() {
state.click();
}
// complete()、status()、timeout()都直接
// 调用state的相应方法即可(略)
}
这里的click()、complete()、status()和timeout()方法体现了Java类多态性的应用。所有这些方法都起着判断和选择动作的作用,即是虽然每一个方法的代码是不含if判断逻辑的,但实际运行时被调用的状态对象却不断变化。在调用click()时会发生哪些事情呢?按照多态性规则,答案依赖于当时传送门的状态。修改后的代码有效地担负起了根据状态执行不同动作的任务,但由于利用了多态性,它变得更加简单了。
字串1
Door2类中的setState()方法现在由DoorState的子类调用。这些DoorState的子类与图1状态机中的相应实体很相似,例如,状态机中Open状态包含Timeout和Click,DoorOpen类则包含两个对应的方法timeout()和click()。DoorOpen类的代码如下:
public class DoorOpen extends DoorState {
public DoorOpen(Door2 door) {
super(door);
}
public void click() {
door.setState(door.STAYOPEN);
}
public void timeout() {
door.setState(door.CLOSING);
}
}
从上面可以看到,利用State设计模式之后,代码变得更简单了。不过,细心的读者或许已经注意到,Door2类用到的“常量”实际上是变量,这给人一种不规范的感觉。假设现在要把这些状态常量移到_DoorConstant接口,这就需要从DoorState类消除Door2实例变量。修改办法是:重新定义DoorState类中的click()、complete()和timeout()变换方法,把一个Door2对象以参数的形式传递给它们。按照这种设计方法,Door2对象调用状态变换方法,例如click()时,将采用state.click(this)的形式。
Tags:
责任编辑:
上一篇:系统约定:用UML描述工作流管理 下一篇:精心打造Team的组织架构
您的评论
·用户发表意见仅代表其个人意见,并且承担一切因发表内容引起的纠纷和责任
·本站管理人员有权在不通知用户的情况下删除不符合规定的评论信息或留做证据
·请客观的评价您所看到的资讯,提倡就事论事,杜绝漫骂和人身攻击等不文明行为
·本站管理人员有权在不通知用户的情况下删除不符合规定的评论信息或留做证据
·请客观的评价您所看到的资讯,提倡就事论事,杜绝漫骂和人身攻击等不文明行为
精彩推荐
最新资讯


您的位置: