状态模式
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类
UML
Java
- 定义状态接口:
public interface State { void method(); }
- 实现具体状态类:
public class State1 implements State { @Override public void method() { System.out.println("execute the first opt!"); } }
public class State2 implements State { @Override public void method() { System.out.println("execute the second opt!"); } }
- 实现状态切换类Context:
public class Context { private State state; public Context(State state) { this.state = state; } public State getState() { return state; } public void setState(State state) { this.state = state; } public void method() { state.method(); } }
- 测试代码:
public class StateTest { public static void main(String[] args) { State state = new State1(); Context context = new Context(state); context.method(); context.setState(new State2()); context.method(); } }
- 测试结果:
execute the first opt! execute the second opt!
Scheme
- 基于消息传递实现状态1和状态2:
(define (make-state-1) (define (operation) (begin (display "execute the first opt!") (newline))) (define (dispatch m) (cond ((eq? m 'operation) operation) (else (error "Unknown request -- MAKE-STATE-1" m)))) dispatch) ;; ((make-state-1) 'operation)
(define (make-state-2) (define (operation) (begin (display "execute the second opt!") (newline))) (define (dispatch m) (cond ((eq? m 'operation) operation) (else (error "Unknown request -- MAKE-STATE-2" m)))) dispatch)
- 实现状态切换:
(define (make-context state) (define (change s) (set! state s)) (define (method) ((state 'operation))) (define (dispatch m) (cond ((eq? m 'change) change) ((eq? m 'method) method) (else (error "Unknown request -- MAKE-Context" m)))) dispatch)
- 测试代码:
(define context (make-context (make-state-1))) ;; => ;Value: context ((context 'method)) ;; => execute the first opt! ((context 'change) (make-state-2)) ;; => #[compound-procedure 27 dispatch] ((context 'method)) ;; => execute the second opt!
状态
既然状态在真实世界里存在,那么编程语言应该提供什么能力来处理状态呢?
- OOP语言说“将状态隐藏”。状态仅仅通过访问方法来隐藏和可见
- 传统编程语言(C,Pascal)说状态的可见度由语言的scope规则来决定
- 纯声明式语言说没有状态。系统的全局状态转移到方法里然后从方法里出来。类似于monad(函数式编程语言)和DCG(逻辑语言)等机制被用来隐藏状态,这样它们可以像“有没有状态无所谓”一样来编程,但是对系统状态的完全访问是必需的
OOP语言所选择的“隐藏状态”可能是最坏的选择。它们不是将状态显示出来并寻找减少状态的坏处的方式,而是将状态隐藏起来!