您的位置:首页 > 其它

设计模式 - 状态模式(State)

2017-04-04 17:44 197 查看
State模式允许一个对象在其内部状态改变时改变它的行为。当一个

对象收到其他对象的请求时, 它根据自身的当前状态作出不同的反应。

• 一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为;同时对象的行为引起对象的状态的改变。

• 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常, 有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

通过 state模式去除复杂的状态改变条件语句。

类图:



案例:地铁闸机状态机

若状态机在lock状态收到一个coin事件,状态改变成unlocked状态并执行unlock动作;

若状态机在unlock状态再收到一个coin事件,状态不变显示”thank you”;

若状态机在unlock状态收到一个pass事件,状态改变成locked状态并执行lock动作;

若状态机在lock状态收到一个pass事件,状态不变并报警。



Step 1: 没有使用State模式,Turnstile对象负责接收事件,TurnstileController负责执行动作。

public class Turnstile {
//states
public static final int LOCKED   = 0;
public static final int UNLOCKED = 1;

private TurnstileController controller;
private int state = LOCKED;

public Turnstile(TurnstileController controller) {
this.controller = controller;
}
public void coin() { //coin event
if(state == LOCKED) {//状态改变条件语句
state = UNLOCKED;
unlock();
} else {
thankyou();
}
}
public void pass() { //pass event
if(state == UNLOCKED) {//状态改变条件语句
state = LOCKED;
lock();
} else {
alarm();
}
}
public void unlock() {
controller.unlock();
}
public void lock() {
controller.lock();
}
public void alarm() {
controller.alarm();
}
public void thankyou() {
controller.thankyou();
}
public boolean isLocked() {
return state == LOCKED;
}
public void setLocked() {
state = LOCKED;
}
public boolean isUnlocked() {
return state == UNLOCKED;
}
public void setUnlocked() {
state = UNLOCKED;
}
}


public class TurnstileController {
public void unlock() {
System.out.println("unlocked turnstile");
}
public void thankyou() {
System.out.println("thank you");
}
public void lock() {
System.out.println("Locked turnstile");
}
public void alarm () {
System.out.println("Can not pass as it is locked");
}
}


测试代码:

public class TurnstileTest {
@Test
public void testTurntileTest() {
TurnstileController controller = new TurnstileController();
Turnstile turntile = new Turnstile(controller);
assertTrue(turntile.isLocked());
turntile.coin();
assertTrue(turntile.isUnlocked());

turntile.coin();
assertTrue(turntile.isUnlocked());

turntile.pass();
assertTrue(turntile.isLocked());

turntile.pass();
assertTrue(turntile.isLocked());

}
}


Step 2: 使用State模式重构去除这些状态改变条件语句。

可以识别出coin()和pass()方法里有状态改变条件语句,定义一个State的接口或抽象超类,将这些方法复制到State的接口或抽象超类 (将上下文类Turnstile传入State中的方法,State的实现类可以调用上下文的方法):

public interface TurnstileState {
public void coin(Turnstile turnstile);
public void pass(Turnstile turnstile);
}


定义实现TurnstileState接口的两个State类:

public class LockedTurntileState implements TurnstileState {
public void coin(Turnstile turnstile) { //coin event
turnstile.setUnlocked();
turnstile.unlock();
}
public void pass(Turnstile turnstile) { //pass event
turnstile.alarm();
}
}


public class UnlockedTurnstileState implements TurnstileState {
public void coin(Turnstile turnstile) {
turnstile.thankyou();
}
public void pass(Turnstile turnstile) {
turnstile.setLocked();
turnstile.lock();
}
}


Step 3: 重构Turnstile,Turnstile称为上下文(context),上下文对象将状态相关的行为委托到状态对象上;上下文对象有一个初始的状态对象。

1) 将状态类型码换成 状态对象

2) coin() 和 pass() 委托给当前的状态对象

public class Turnstile {
//re
b2ac
place state types with state objects
public static final TurnstileState lockedState = new LockedTurntileState();
public static final TurnstileState unlockedState = new UnlockedTurnstileState();

private TurnstileController controller;
private TurnstileState state = lockedState;//初始的状态对象

public Turnstile(TurnstileController controller) {
this.controller = controller;
}
public void coin() {
state.coin(this); //delegate state object
}
public void pass() {
state.pass(this); ////delegate state object
}
public void unlock() {
controller.unlock();
}
public void lock() {
controller.lock();
}
public void alarm() {
controller.alarm();
}
public void thankyou() {
controller.thankyou();
}
public boolean isLocked() {
return state == lockedState;
}
public void setLocked() {
state = lockedState;
}
public boolean isUnlocked() {
return state == unlockedState;
}
public void setUnlocked() {
state = unlockedState;
}
}


通过将Context类中的State变量封装成状态类,状态相关的行为委托到状态对象上,从而去除Context中状态相关的方法中复杂状态改变条件语句。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  设计模式