设计模式

来源:互联网 发布:sql pf start with 编辑:程序博客网 时间:2024/06/12 00:56

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 {    //replace 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中状态相关的方法中复杂状态改变条件语句。

0 0