文章目录
- 描述
-
- 定义
- 类型
- 动机
- UML类图
- 时序图
- 实现
-
- 主要角色
- 示例
- 适用场景
- 优点
- 缺点
- 相关模式
描述
定义
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
类型
对象行为型模式
动机
对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。
UML类图
时序图
实现
主要角色
- Context:上下文
- 定义客户感兴趣的接口。
- 维护一个ConcreteState子类的实例,这个实例定义当前状态。
- State:状态接口类
- 定义一个接口以封装与Context的一个特定状态相关的行为。
- ConcreteState:具体状态类
- 每一子类实现一个与Context的一个状态相关的行为。
示例
- Context:上下文。谁定义状态转换:如果规则是固定的,那么可在Context中完全实现。然而若让State子类自身指定后继状态以及何时进行转换,通常更灵活更合适,但缺点是在各子类之间产生了实现依赖。
public class Context { private State state; public Context(State state) { this.state = state; } public State getState() { return state; } public void changeState() { this.state = this.state.next(); } public void request() { state.handle(this); } }
- State:状态接口类。创建和销毁State对象通常有两种做法:1) 仅当需要State对象时才创建它们并随后销毁它们;2) 提前创建它们并且始终不销毁它们。
interface State { void handle(Context context); State next(); }
- ConcreteState:具体状态类
public class ConcreteState1 implements State { @override public void next() { return new ConcreteState2(); } @override public void handle(Context context) { System.out.println("ConcreteState1"); } } public class ConcreteState2 implements State { @override public void next() { return new ConcreteState1(); } @override public void handle(Context context) { System.out.println("ConcreteState2"); } }
- Client:客户类
public class Client { public static void main(String[] args) { Context context = new Context(new ConcreteState1()); context.request(); context.changeState(); context.request(); } }
适用场景
- 对象的行为随它的状态改变而改变,并且它必须在运行时刻动态决定。
- 条件、分支语句的代替者。一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。
优点
- 将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
- 封装了转换规则。通过定义新的子类可以很容易的增加新的状态和转换。
- 使得状态转换显式化。为不同的状态引入独立的对象使得转换变得更加明确。而且可保证状态转换是原子的。
- 状态对象可被共享。如果State对象没有实例变量——即它们表示的状态完全以它们的类型来编码——那么各Context对象可以共享一个State对象。
缺点
- 会增加系统类和对象的个数。
- 对"开闭原则"的支持不太好。增加新的状态类需要修改那些负责状态转换的源代码,而且修改某个状态类的行为也需修改对应类的源代码。
相关模式
- Flyweight:通过享元模式来实现何时以及怎样共享状态对象。
- Singleton:状态对象通常是单例。