当一个对象的内部状态发生改变时,会导致其行为的改变;
适用场景:
- 一个对象,存在多个状态,状态可以相互转换;
- 不同状态下,行为不同,用来减少 if…else 子句;
优点:
- 可以将 不同的状态 隔离,每个状态都是一个 单独的类;
- 可以将 各种状态 的 转换逻辑,分布到 状态 的子类中,减少相互依赖;
- 增加 新状态,操作简单;
缺点:
- 如果 状态数量 比较多,状态类的数量会增加,业务场景系统变得很复杂; 如果业务中某个对象由几十上百个状态,就会很复杂,这时就需要对状态进行拆分处理;
类图
bad
class Battery {
constructor() {
this.amount = 'high'; // 电量很高
}
show() {
if (this.amount == 'high') {
console.log('绿色');
this.amount = 'middle';
} else if (this.amount == 'middle') {
console.log('黄色');
this.amount = 'low';
} else {
console.log('红色');
}
}
}
let battery = new Battery();
battery.show();
battery.show();
battery.show();
/*
问题:
- show 违反开放-封闭原则
- show 方法逻辑太多太复杂
- 颜色状态切换不明显
- 过多的 if/else 让代码不可维护
*/
good
class Battery {
constructor(state) {
this.amount = 'high'; // 电量很高
this.state = new SuccessState();
}
show() {
this.state.show();
if (this.amount == 'high') {
this.amount = 'middle';
this.setState(new WarningState());
} else if (this.amount == 'middle') {
this.amount = 'low';
this.setState(new DangerState());
}
}
setState(state) {
this.state = state;
}
}
class SuccessState {
constructor(battery) {
this.battery = battery;
}
show() {
console.log(`绿色 ${battery.amount}`);
}
}
class WarningState {
constructor(battery) {
this.battery = battery;
}
show() {
console.log(`黄色 ${battery.amount}`);
}
}
class DangerState {
constructor(battery) {
this.battery = battery;
}
show() {
console.log(`红色 ${battery.amount}`);
}
}
let battery = new Battery();
battery.show();
battery.show();
battery.show();
经典场景
点赞
let likeState = {
render(element) {
element.innerHTML = '赞👍';
}
}
let likedState = {
render(element) {
element.innerHTML = '取消';
}
}
class Button {
constructor(container) {
this.liked = false;
this.state = likeState; // 初始状态
this.element = document.createElement('button');
container.appendChild(this.element);
this.render();
}
setState(state) {
this.state = state;
this.render();
}
render() {
this.state.render(this.element);
}
}
// 测试
let button = new Button(document.body);
button.element.addEventListener('click', () => {
button.setState(button.liked ? likeState : likedState);
button.liked = !button.liked;
});
promise
class Promise {
constructor(fn) {
this.state = 'initial'; // 初始状态
this.successes = [];
this.fails = [];
let resolve = (data) => {
this.state = 'fulfilled';
this.successes.forEach(item => item(data));
}
let reject = (error) => {
this.state = 'failed';
this.fails.forEach(item => item(error));
}
fn(resolve, reject);
}
then(success, fail) {
this.successes.push(success);
this.fails.push(fail);
}
}
let p = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(1);
}, 1000);
});
p.then((data) => console.log('成功'), error => console.error('失败'));
有限状态机
什么是有限状态机?
- 事物拥有多种状态,任一时间只会处于一种状态不会处于多种状态;
- 动作可以改变事物状态,一个动作可以通过条件判断,改变事物到不同的状态,但是不能同时指向多个状态,一个时间,就一个状态;
- 状态总数是有限的;
- form:当前行为从哪个状态来;
- to:当前行为执行完会过渡到哪个状态;
- name:当前行为的名字;
// var StateMachine = require('javascript-state-machine'); // 有限状态机
class StateMachine {
constructor(options) {
let { initState, transitions, methods } = options;
this.state = initState;
transitions.forEach(transition => {
let { from, to, name } = transition;
this[name] = function () {
if (this.state == from) {
this.state = to;
let onMethod = 'on' + name.slice(0, 1).toUpperCase() + name.slice(1);
methods[onMethod] && methods[onMethod]();
}
}
});
}
}
var fsm = new StateMachine({
initState: 'solid', // 初始状态
transitions: [
{
name: 'melt',
from: 'solid',
to: 'liquid'
},
{
name: 'freeze',
from: 'liquid',
to: 'solid'
},
{
name: 'vaporize',
from: 'liquid',
to: 'gas'
},
{
name: 'condense',
from: 'gas',
to: 'liquid'
}
],
methods: {
// 融化
onMelt: function () {
console.log('I melted')
},
// 冷冻
onFreeze: function () {
console.log('I froze')
},
// 蒸发
onVaporize: function () {
console.log('I vaporized')
},
// 凝结
onCondense: function () {
console.log('I condensed')
}
}
});
fsm.melt();
fsm.vaporize();
打赏作者
您的打赏是我前进的动力
微信
支付宝
迭代器模式
上一篇
评论