状态模式(State)
当一个对象的内部状态发生改变时,会导致其行为的改变,这看起来像是改变了对象。
主要目的就是将条件判断的不同结果转化为状态对象的内部状态。
解决多分支判断问题
一般判断形势 (当新增需求时那么就需要添加新的判断条件)
// 展示结果 function showResult(state) { if (state == 0) { // 处理结果0 console.log('这是第一种情况'); } else if (state == 1) { // 处理结果1 console.log('这是第二种情况'); } else if (state == 2) { // 处理结果2 console.log('这是第三种情况'); } else if (state == 3) { // 处理结果3 console.log('这是第四种情况'); } } showResult(2); // 这是第三种情况
状态对象的实现 (状态模式的基本雏形)
// 投票结果状态对象 const ResutlState = (function () { // 判断结果保存在内部状态中 var State = { // 每种状态作为一种独立方法保存 state0: function () { // 处理结果0 console.log('这是第一种情况'); }, state1: function () { // 处理结果1 console.log('这是第二种情况'); }, state2: function () { // 处理结果2 console.log('这是第三种情况'); }, state3: function () { // 处理结果3 console.log('这是第四种情况'); } }; // 获取某一种状态并执行其对应的方法 function show(type) { State[`state${type}`] && State[`state${type}`](); } return { // 返回调用状态方法接口 show } }()); ResutlState.show(2); // 这是第三种情况
超级玛丽
示例:
if ... else ...
形势判断角色动作:// 单动作条件判断 每增加一个动作就需要添加一个判断 function playerController(state) { if (state === 'move') { console.log('移动'); } else if (state === 'jump') { console.log('跳跃'); } else { console.log('idle'); } } // 复合动作对条件判断的开销是翻倍的 function playerController(state1, state2) { if (state1 === 'move') { console.log('移动'); } else if (state1 === 'move' && state2 === 'shoot') { console.log('移动射击'); } else if (state1 === 'jump') { console.log('跳跃'); } else if (state1 === 'jump' && state2 === 'shoot') { console.log('跳跃射击'); } else if (state1 === 'idle' && state2 === 'shoot') { console.log('站立射击'); } else { console.log('idle'); } }
状态优化
形势:// 创建超级玛丽状态类 const Player = function () { // 内部状态私有变量(缓存当前状态) let _currentState = []; // 动作与状态方法映射 const state = { // 跳跃 jump() { console.log('jump'); }, // 移动 move() { console.log('move'); }, // 射击 shoot() { console.log('shoot'); }, // 蹲下 squat() { console.log('squat'); } }; // 动作控制类,返回接口方法 changeState、action return { // 改变状态方法 - 组合动作通过传递多个参数实现 changeState(...args) { // 重置并向内部状态中添加动作 _currentState = args; // 返回动作控制类 return this; }, // 执行动作 action() { console.log('触发一次动作'); // 遍历内部状态保存的动作 - 如果该动作存在则执行 _currentState.forEach(key => state[key] && state[key]()) return this; } }; }; // 创建一个超级玛丽 const player = new Player(); player .changeState('jump', 'shoot') // 改变为`跳跃`与`射击`动作组合 .action() // 执行动作 触发一次动作 ---> jump - shoot .action() // 执行动作 触发一次动作 ---> jump - shoot .changeState('shoot') // 改变为`射击`动作 .action(); // 执行动作 触发一次动作 ---> shoot
特点:
状态模式既是
解决程序中臃肿的分支判断语句问题
,将每个分支
转化为一种状态
独立出来
,方便
每种状态
的管理
又不至于每次执行时遍历所有分支
。