友情支持

如果您觉得这个笔记对您有所帮助,看在D瓜哥码这么多字的辛苦上,请友情支持一下,D瓜哥感激不尽,😜

支付宝

微信

有些打赏的朋友希望可以加个好友,欢迎关注D 瓜哥的微信公众号,这样就可以通过公众号的回复直接给我发信息。

wx jikerizhi

公众号的微信号是: jikerizhi因为众所周知的原因,有时图片加载不出来。 如果图片加载不出来可以直接通过搜索微信号来查找我的公众号。

22. 状态模式

22.1. 定义

根据 GoF 的著名著作 《设计模式》,状态模式的定义如下:

状态模式(State)

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

— Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides
《设计模式》

22.2. 类图

Diagram

MartinFowler曾在《重构》中写过一个很重要的代码坏味道,叫做‘Long Method’,方法如果过长其实极有可能是有坏味道了。

面向对象设计其实就是希望做到代码的责任分解。

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。

State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为。

ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。

Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。

状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来[DP]。

将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换[DP]。

这样做的目的就是为了消除庞大的条件分支语句,大的分支判断会使得它们难以修改和扩展,就像我们最早说的刻版印刷一样,任何改动和变化都是致命的。状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖,好比把整个版面改成了一个又一个的活字,此时就容易维护和扩展了。

当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。

代码 127. state/ConcreteStateA.java 类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package com.diguage.didp.state;

/**
 * ConcreteStateA 类
 *
 * @author D瓜哥, https://www.diguage.com/
 * @since 2017-05-19 17:53:36
 */
public class ConcreteStateA extends State {
  @Override
  public void handle(Context context) {
    context.setState(new ConcreteStateB());
  }
}
代码 128. state/ConcreteStateB.java 类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package com.diguage.didp.state;

/**
 * ConcreteStateB 类
 *
 * @author D瓜哥, https://www.diguage.com/
 * @since 2017-05-19 17:53:36
 */
public class ConcreteStateB extends State {
  @Override
  public void handle(Context context) {
    context.setState(new ConcreteStateC());
  }
}
代码 129. state/ConcreteStateC.java 类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package com.diguage.didp.state;

/**
 * ConcreteStateC 类
 *
 * @author D瓜哥, https://www.diguage.com/
 * @since 2017-05-19 17:53:36
 */
public class ConcreteStateC extends State {
  @Override
  public void handle(Context context) {
    context.setState(new ConcreteStateA());
  }
}
代码 130. state/Context.java 类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.diguage.didp.state;

/**
 * Context 类
 *
 * @author D瓜哥, https://www.diguage.com/
 * @since 2017-05-19 17:53:36
 */
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;
    System.out.println("当前状态:" + state.getClass().getName());
  }

  public void request() {
    state.handle(this);
  }
}
代码 131. state/State.java 类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
package com.diguage.didp.state;

/**
 * State 类
 *
 * @author D瓜哥, https://www.diguage.com/
 * @since 2017-05-19 17:53:36
 */
public abstract class State {
  public abstract void handle(Context context);
}
代码 132. state/Client.java 类
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package com.diguage.didp.state;

/**
 * @author D瓜哥, https://www.diguage.com/
 * @since 2017-05-26
 */
public class Client {
  public static void main(String[] args) {
    Context context = new Context(new ConcreteStateA());
    context.request();
    context.request();
    context.request();
    context.request();
  }
}

22.3. 常见示例

  1. java.util.Iterator