状态模式(State Pattern): 允许一个对象在其内部状态改变时改变它的行为. 对象看起来似乎修改了它的类.
设计模式-概述
状态对于一个对象来说, 是一个很平常的属性, 比如一个任务对象, 它有未开始,已开始,进行中,已完成等等各种状态, 为了针对不同的状态变更, 来做不同的处理, 如果不用设计模式的写法, 将会产生大量的 if-else
, 一旦新需求到来, 需要新的状态, 就会越写越多, 导致代码可读性和可维护性降低. 使用状态模式可以解决这个问题, 它能解决复杂对象的状态切换以及不同状态下的行为的封装问题
结构
状态模式引入了抽象状态类和具体状态类, 包含了3种角色.
- 环境类(Context): 是一个拥有多个状态的对象. 环境会随着状态不同, 而有不同的行为.
- 状态抽象类(State): 定义了一个接口, 用来封装某个状态下环境的行为.
- 具体状态类(ConcreteState): 实现了环境的某个状态下的具体的行为.

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 29 30 31 32 33 34 35 36 37
| @startuml state-1 !include common.cuml
Interface(State,"抽象状态") { + handle() : void }
Class(ConcreteStateA,"具体状态A") { + handle() : void }
Class(ConcreteStateB,"具体状态B") { + handle() : void }
Class(Context,"环境") { - state : State + request() : void + setState(State state) : void }
note as N1 public void request() { // todo 自己的处理逻辑a state.handle(); // todo 自己的处理逻辑b } end note
N1 ... Context
ConcreteStateA --|> State ConcreteStateB --|> State
State <--o Context
@enduml
|
代码实现
- 定义三种状态, 并且实现内部行为
- 客户端调用行为方法, 无需关系当前处于何种状态, 具体实现由状态类管理
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| package com.yuda.desigmode;
public class Main3 { public static void main(String[] args) { Context context = new Context(); context.setState(new ConcreteStateA()); context.request(); System.out.println("切换状态"); context.setState(new ConcreteStateB()); context.request(); System.out.println("再次切换状态"); context.setState(new ConcreteStateC()); context.request(); } }
interface State { void handle(); }
class ConcreteStateA implements State {
@Override public void handle() { System.out.println("ConcreteStateA.handle"); } }
class ConcreteStateB implements State {
@Override public void handle() { System.out.println("ConcreteStateB.handle"); } }
class ConcreteStateC implements State {
@Override public void handle() { System.out.println("ConcreteStateC.handle"); } }
class Context { private State state;
public void request() { state.handle(); }
public void setState(State state) { this.state = state; } }
|
结果为:
1 2 3 4 5
| ConcreteStateA.handle 切换状态 ConcreteStateB.handle 再次切换状态 ConcreteStateC.handle
|
有新需求如果需要一个新状态, 只需要新增一个实现就可以了, 不用修改状态的实现.
使用场景
- 对象的行为依赖于它的状态, 切换状态后, 行为也会有变化时.
- 某个对象有大量的状态, 并且随着版本更新换代, 状态会更多时.(即如果发现
if-else
太多, 可以考虑用状态模式)
具体应用
todo 还没见过用, 见到再补