这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战
状态模式
对有状态的对象,把复杂的判断逻辑提取到不同的状态对象中,允许状态对象在其内部状态发生 变化时改变其行为。
模式结构
- 上下文,Context 定义了客户端需要的接口,内部维护一个当前状态,并负责具体状态的切换
- 抽象状态,定义接口,声明上下文中特定状态对应的方法。, 可以一个或多个的行为
- 具体状态,实现抽象状态所对应的行为,并且在需要的情况下进行状态切换
// 上下文类,其中包含状态
class Context {
private state: State;
constructor(state: State) {
this.state = state;
}
// 对请求做处理,当状态变化时允许改变对象
handler() {
this.state.handle(this);
}
}
// 抽象状态类
interface State {
context: Context;
handle(context: Context): void;
}
//
class AState implements State {
context: Context;
handle(context: Context): void {
console.log("当前状态1");
// 状态改变时需要改变其行为,此处将行为改为状态2
this.context = new Context(new BState());
}
}
class BState implements State {
context: Context;
handle(context: Context): void {
console.log("当前状态2");
}
}
(() => {
const hd1 = new AState();
const ctx = new Context(hd1);
ctx.handler(); // 执行第一次后状态切换成状态2
ctx.handler();// 执行的是状态2 的
})();
Context类中保存了对具体状态的引用,且支持其根据不同对象进行切换。State类中存储对于Context对象的反向引用。 然后可以通过该引用从上下文处获取所需信息, 并且能触发状态转移。
主要优点
- 将与特定状态相关的代码放在单独的类中,符合单一职责原理
- 将状态转换显示化,减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
- 引入新状态时无需修改已有状态类的上下文
- 通过消除臃肿的状态机条件语句简化上下文代码
主要缺点
- 如果状态机只有很少的几个状态, 或者很少发生改变, 那么应用该模式可能会显得小题大作。
- 状态模式的使用必然会增加系统的类与对象的个数。
适用场景
- 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。
- 一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时。
- 当相似状态和基于条件的状态机转换中存在许多重复代码时,可使用状态模式。
- 如果某个类需要根据成员变量的当前值改变自身行为,从而需要使用大量的条件语句时,可使用该模式
\