javascript代码实例教程-Javascript设计模式之我见:状态模式

发布时间:2019-02-24 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了javascript代码实例教程-Javascript设计模式之我见:状态模式脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。 大家好!本文介绍状态模式及其在Javascript中的应用。

 

模式介绍

 

定义

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

 

状态模式主要解决的是控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化

 

类图及说明

 

 

State:抽象状态

 

接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换

 

Concrestate:具体状态

 

每一个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理。通俗地说,就是本状态下要做的事情,以及本状态如何过渡到其他状态。

 

Context:环境 

 

定义客户端需要的接口,并且负责具体状态的切换。

 

应用场景

一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。

代码中包含大量与对象状态有关的条件语句:一个操作中含有庞大的多分支的条件(if else(或swITch case)语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常 , 有多个操作包含这一相同的条件结构。 State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

优点

避免了过多的 swith…case 或者 if..else 语句的使用,避免了程序的复杂性

很好的使用体现了开闭原则和单一职责原则,每个状态都是一个子类,你要增加状态就增加子类,你要修改状态,你只修改一个子类就可以了

封装性非常好,这也是状态模式的基本要求。状态变换放置到了类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的变换。

缺点 

具体状态类可能会有很多个,不好管理。

状态模式在Javascript中的应用

 

我的理解

@R_406_541@State具体状态类有两个职责:处理本状态必须完成的任务;过渡到其他状态。

可以采自下而上的方法来实现状态类,即先实现Concretestate类,然后再将ConcreteState类的共性提取出来,形成父类State。

类图及说明

 

 

User:使用者

 

使用者具有不同的状态,它创建Context类并将状态的逻辑委托给Context类处理。

 

示例

小时候大家应该都玩过魂斗罗游戏吧,魂斗罗了无敌道具后会变成刀枪不入,吃了火力增强道具后会变成杀人机器。让我们来看看它的状态是如何转换的。

 

状态图

 

 

魂斗罗Warrior有NORMAL、INVINCIBLE、POWER、DEAD四个状态,每个状态都有beNormal、beinvincible、bePower、dead四个方法。有timeOver、getInvincible、getPower、beShotDead四个触发状态的事件。

 

类图

 

 

代码

代码中使用的库:YOOP

 

Warrior

 

 

    VAR Warrior = yyC.Class({

        PRivate: {

            _state: null

        },

        Public: {

            //*事件标志

 

            _getInvincible: false,

            _getPower: false,

            _timeOver: false,

            _beShotDead: false,

 

            setState: function (state) {

                this._state = state;

            },

            //*状态方法

 

            beNormal: function () {

                switch (this._state) {

                    case  Warrior.NORMAL_STATE:

                        //本状态beNormal方法的逻辑。已经处于NORMAL状态,不用再转换为NORMAL状态了

                        console.LOG("恢复正常");

                        break;

                    case Warrior.INVINCIBLE_STATE:

                        //INVINCIBLE状态下beNormal方法的逻辑

                        console.log("恢复正常");

                        //从INVINCIBLE状态转换到NORMAL状态

                        this.setState(Warrior.NORMAL_STATE);

                        break;

                    case Warrior.POWER_STATE:

                        //POWER状态下beNormal方法的逻辑

                        console.log("恢复正常");

                        //从POWER状态转换到NORMAL状态

                        this.setState(Warrior.NORMAL_STATE);

                        break;

                    case Warrior.DEAD_STATE:

                        //不能起死回生

                        break;

                }

            },

            beInvincible: function () {

                switch (this._state) {

                    case  Warrior.NORMAL_STATE:

                        console.log("无敌");

                        this.setState(Warrior.INVINCIBLE_STATE);

                        break;

                    case Warrior.INVINCIBLE_STATE:

                        console.log("无敌");

                        break;

                    case Warrior.POWER_STATE:

                        console.log("无敌");

                        this.setState(Warrior.INVINCIBLE_STATE);

                        break;

                    case Warrior.DEAD_STATE:

                        break;

                }

            },

            bePower: function () {

                switch (this._state) {

                    case  Warrior.NORMAL_STATE:

                        console.log("火力增强");

                        this.setState(Warrior.POWER_STATE);

                        break;

                    case Warrior.INVINCIBLE_STATE:

                        console.log("火力增强");

                        this.setState(Warrior.POWER_STATE);

                        break;

                    case Warrior.POWER_STATE:

                        console.log("火力增强");

                        break;

                    case Warrior.DEAD_STATE:

                        break;

                }

            },

            dead: function () {

                switch (this._state) {

                    case  Warrior.NORMAL_STATE:

                        console.log("死亡");

                        this.setState(Warrior.DEAD_STATE);

                        break;

                    case Warrior.INVINCIBLE_STATE:

                        //都无敌了当然不会死亡

                        break;

                    case Warrior.POWER_STATE:

                        console.log("死亡");

                        this.setState(Warrior.DEAD_STATE);

                        break;

                    case Warrior.DEAD_STATE:

                        console.log("死亡");

                        break;

                }

            },

 

            action: function () {

                //*此处进行触发状态的事件判断

 

                if (this._timeOver) {

                    this.beNormal();

                }

                else if (this._getInvincible) {

                    this.beInvincible();

                }

                else if (this._getPower) {

                    this.bePower();

                }

                else if (this._beShotDead) {

                    this.dead();

                }

            }

        },

        Static: {

            NORMAL_STATE: 1,

            INVINCIBLE_STATE: 2,

            POWER_STATE: 3,

            DEAD_STATE: 4

        }

    });

 

场景类

 

 

    function _resetFlag(warrior) {

        warrior._getInvincible = false;

        warrior._getPower = false;

        warrior._timeOver = false;

        warrior._beShotDead = false;

    }

    function _getInvincible(warrior) {

        _resetFlag(warrior);

 

        warrior._getInvincible = true;

    }

    function _getPower(warrior) {

        _resetFlag(warrior);

 

        warrior._getPower = true;

    }

    function _beShotDead(warrior) {

        _resetFlag(warrior);

 

        warrior._beShotDead = true;

    }

 

 

    function main() {

        var warrior = new Warrior();

 

        //初始状态为Normal

        warrior.setState(Warrior.NORMAL);

 

        //获得无敌道具,进入无敌状态

        _getInvincible(warrior);

 

        warrior.action();

 

        //获得火力增强道具,进入火力增强状态

        _getPower(warrior);

 

        warrior.action();

 

        //被击中,进入死亡状态

        _beShotDead(warrior);

 

        warrior.action();

    }

 

运行结果

 

 

示例分析

我们来看看这段程序的问题。

 

实现类Warrior用了大量的switch...case判断,增加了大量代码,可读性和可维护性差。

扩展性差。

如果要增加1个状态,则beNormal、beInvincible、bePower、dead方法中都要增加判断条件,这不符合开闭原则。

使用状态模式

类图

 

 

代码

State

 

 

var State = YYC.AClass({

    Public: {

        setContext: function (context) {

            this.P_context = context;

        }

    },

    Protected: {

        P_context: null

    },

    Abstract: {

        beNormal: function () {

        },

        beInvincible: function () {

        },

        bePower: function () {

        },

        dead: function () {

        }

    }

});

 

NormalState

 

 

var NormalState = YYC.Class(State, {

    Public: {

        //*在具体状态类中进行触发状态的事件判断

 

        beNormal: function () {

            if (this.P_context.warrior.timeOver) {

                //本状态逻辑

                console.log("恢复正常");

            }

        },

        beInvincible: function () {

            if (this.P_context.warrior.getInvincible) {

                //过度到无敌状态的逻辑

                this.P_context.setState(Context.InvincibleState);

                this.P_context.beInvincible();

            }

        },

        bePower: function () {

            if (this.P_context.warrior.getPower) {

                //过度到火力增强状态的逻辑

                this.P_context.setState(Context.PowerState);

                this.P_context.bePower();

            }

        },

        dead: function () {

            if (this.P_context.warrior.beShotDead) {

                //过度到死亡状态的逻辑

                this.P_context.setState(Context.Deadstate);

                this.P_context.dead();

            }

        }

    }

});

 

InvincibleState

 

 

var InvincibleState = YYC.Class(State, {

    Public: {

        beNormal: function () {

            if (this.P_context.warrior.timeOver) {

                this.P_context.setState(Context.NormalState);

                this.P_context.beNormal();

            }

        },

        beInvincible: function () {

            if (this.P_context.warrior.getInvincible) {

                console.log("无敌");

            }

        },

        bePower: function () {

            if (this.P_context.warrior.getPower) {

                this.P_context.setState(Context.PowerState);

                this.P_context.bePower();

            }

        },

        dead: function () {

            //都无敌了当然不会死亡

        }

    }

});

 

PowerState

 

 

var PowerState = YYC.Class(State, {

    Public: {

        beNormal: function () {

            if (this.P_context.warrior.timeOver) {

                this.P_context.setState(Context.NormalState);

                this.P_context.beNormal();

            }

        },

        beInvincible: function () {

            if (this.P_context.warrior.getInvincible) {

                this.P_context.setState(Context.InvincibleState);

                this.P_context.beInvincible();

            }

        },

        bePower: function () {

            if (this.P_context.warrior.getPower) {

                console.log("火力增强");

            }

        },

        dead: function () {

            if (this.P_context.warrior.beShotDead) {

                this.P_context.setState(Context.DeadState);

                this.P_context.dead();

            }

        }

    }

});

 

DeadState

 

 

var DeadState = YYC.Class(State, {

    Public: {

        beNormal: function () {

            //不能起死回生

        },

        beInvincible: function () {

            //挂都挂了,还怎么无敌

        },

        bePower: function () {

            //挂都挂了,还怎么火力增强

        },

        dead: function () {

            if (this.P_context.warrior.beShotDead) {

                console.log("死亡");

            }

        }

    }

});

 

Context

 

 

var Context = YYC.Class({

    Init: function (warrior) {

        this.warrior = warrior;

    },

    Private: {

        _state: null

    },

    Public: {

        warrior: null,

 

        setState: function (state) {

            this._state = state;

            //把当前的上下文通知到当前状态类对象中

            this._state.setContext(this);

        },

        beNormal: function () {

            this._state.beNormal();

        },

        beInvincible: function () {

            this._state.beInvincible();

        },

        bePower: function () {

            this._state.bePower();

        },

        dead: function () {

            this._state.dead();

        }

    },

    Static: {

        NormalState: new NormalState(),

        InvincibleState: new InvincibleState(),

        PowerState: new PowerState(),

        DeadState: new DeadState()

    }

});

 

Warrior

 

 

var Warrior = YYC.Class({

    Init: function () {

        this._context = new Context(this);

        //设置初始状态

        this._context.setState(Context.NormalState);

    },

    Private: {

        _context: null

    },

    Public: {

        //*事件标志

 

        getInvincible: false,

        getPower: false,

        timeOver: false,

        beShotDead: false,

 

        action: function () {

            this._context.beNormal();

            this._context.beInvincible();

            this._context.bePower();

            this._context.dead();

        }

    }

});

 

场景类Client

 

 

function _resetFlag(warrior) {

    warrior.getInvincible = false;

    warrior.getPower = false;

    warrior.imeOver = false;

    warrior.beShotDead = false;

}

function _getInvincible(warrior) {

    _resetFlag(warrior);

 

    warrior.getInvincible = true;

}

function _getPower(warrior) {

    _resetFlag(warrior);

 

    warrior.getPower = true;

}

function _beShotDead(warrior) {

    _resetFlag(warrior);

 

    warrior.beShotDead = true;

}

 

 

function main() {

    var warrior = new Warrior();

 

    //获得无敌道具,进入无敌状态

    _getInvincible(warrior);

 

    warrior.action();

 

    //获得火力增强道具,进入火力增强状态

    _getPower(warrior);

 

    warrior.action();

 

    //被击中,进入死亡状态

    _beShotDead(warrior);

 

    warrior.action();

}

 

运行结果

 

 

示例分析

  将触发状态的事件判断移到Warrior类中

目前是在具体状态类中进行触发状态的事件判断,这样造成了重复判断。可以将判断提出来,放到Warrior类的action中进行判断:

 

Warrior

 

 

        action: function () {

            if (this.timeOver) {

                this._context.beNormal();

            }

            else if (this.getInvincible) {

                this._context.beInvincible();

            }

            else if (this.getPower) {

                this._context.bePower();

            }

            else if (this.beShotDead) {

                this._context.dead();

            }

        }

 

NormalState(其它三个具体状态类做相同的重构)

 

 

var NormalState = YYC.Class(State, {

    Public: {

        beNormal: function () {

            //本状态逻辑

            console.log("恢复正常");

        },

        beInvincible: function () {

            //过度到无敌状态的逻辑

            this.P_context.setState(Context.InvincibleState);

            this.P_context.beInvincible();

        },

        bePower: function () {

            //过度到火力增强状态的逻辑

            this.P_context.setState(Context.PowerState);

            this.P_context.bePower();

        },

        dead: function () {

            //过度到死亡状态的逻辑

            this.P_context.setState(Context.DeadState);

            this.P_context.dead();

        }

    }

});

 

觉得可用,就经常来吧! 脚本宝典 欢迎评论哦! js脚本,巧夺天工,精雕玉琢。小宝典献丑了!

脚本宝典总结

以上是脚本宝典为你收集整理的javascript代码实例教程-Javascript设计模式之我见:状态模式全部内容,希望文章能够帮你解决javascript代码实例教程-Javascript设计模式之我见:状态模式所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。