美文网首页
JavaScript设计模式 | 18-状态模式

JavaScript设计模式 | 18-状态模式

作者: 夏海峰 | 来源:发表于2019-03-01 15:29 被阅读19次

1、模式定义

状态模式,当一个对象的内部状态发生改变时,这会导致其行为的改变。这看起来像是改变了对象。

2、为什么需要状态模式?它能解决什么问题?

状态模式,主要目的就是把条件判断的不同结果,转化为状态对象的内部状态,然后提供一个能够调用该对象的内部状态的接口方法。如此,我们就能够方便地增加、修改、调用和删除这个对象的内部状态,帮助我们更好地管理这个对象的内部状态。

像如下的代码,即是根据对象的不同状态来执行不同的功能逻辑。这种使用条件判断来实现的方式,非常不便于后期的维护,当有状态需要增、删、改时,就会遇到一系列麻烦。

function showResult(result) {
    if (result == 0) {
        // 执行功能1
    } else if (result == 1) {
        // 执行功能2
    } else if (result == 2) {
        // 执行功能3
    }
}

3、使用状态模式 来优化使用条件判断实现的状态分支

下面代码就是状态模式的雏形,这样我们就可以方便地修改、增加、调用和删除对象的内部状态。这比使用条件语句实现的状态分支具有更多的优势。

var ResultState = function() {
    var States = {
        state0: function() {
            console.log('这是对象的第一种状态');
        },
        state1: function() {
            console.log('这是对象的第二种状态');
        },
        state2: function() {
            console.log('这是对象的第三种状态');
        },
        state3: function() {
            console.log('这是对象的第四种状态');
        },
        state4: function() {
            console.log('这是对象的第五种状态');
        }
    }
    function show(result) {
        // 如果存在该状态,就执行其对应的功能逻辑
        States['state' + result] && States['state' + result]();
    }
    return { show: show }
}();
// 小测一下:执行第四种状态
ResultState.show(3);

4、状态模式 举例

// 状态模式:超级玛丽的状态模式

var MarryState = function() {
    // 当前状态
    var _curState = {};
    // 默认的四种状态
    var states = {
        jump: function() {
            console.log('超级玛丽 在跳跃');
        },
        move: function() {
            console.log('超级玛丽 在移动');
        },
        shoot: function() {
            console.log('超级玛丽 在躲击');
        },
        squat: function() {
            console.log('超级玛丽 已蹲下');
        }
    };
    // 状态控制
    var Action = {
        // 改变对象内部状态
        changeState: function() {
            var arg = arguments;
            _curState = {};
            if (arg.length) {
                for (var i=0; i<arg.length; i++) {
                    _curState[arg[i]] = true;
                }
            }
            return this;
        },
        // 执行一遍功能逻辑
        goes: function() {
            console.log('触发一次动作');
            for (var i in _curState) {
                states[i] && states[i]();
            }
            return this;
        }
    }
    return {
        change: Action.changeState,
        goes: Action.goes
    }
}

现在,我们已经把超级玛丽的状态模式创建出来了。我们有两种方式来使用它。

// 使用方式一
MarryState().change('jump', 'shoot')  // 改变对象内部状态
    .goes()     // 执行动作
    .goes()
    .change('shoot') // 改变对象内部状态
    .goes();

// 使用方式二
var marry = new MarryState();
marry.change('jump', 'shoot')  // 改变对象内部状态
    .goes()
    .goes()
    .change('shoot')  // 改变对象内部状态
    .goes();

像这样,改变对象的状态变得如此简单,状态一旦改变其行为结果立即改变。并且思路是非常清晰的。

5、小结

使用状态模式,我们可以把条件判断中的每一种情况独立出来进行管理,解决了分支条件之间的耦合问题。

状态模式既能解决程序中臃肿的分支判断语句,还能把每个分支转化成一种独立的状态,并方便每种状态的管理。程序产出何种结果,取决于用户选择了哪种状态,而选择状态又是在程序运行时被决定的。


END 2019-03-01

相关文章

网友评论

      本文标题:JavaScript设计模式 | 18-状态模式

      本文链接:https://www.haomeiwen.com/subject/ggbduqtx.html