Javascript设计模式之我见:状态模式
大家好!本文介绍状态模式及其在Javascript中的应用。模式介绍
定义
当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。
类图及说明
State:抽象状态
接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换
ConcreState:具体状态
每一个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理。通俗地说,就是本状态下要做的事情,以及本状态如何过渡到其他状态。
Context:环境
定义客户端需要的接口,并且负责具体状态的切换。
应用场景
一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
代码中包含大量与对象状态有关的条件语句:一个操作中含有庞大的多分支的条件(if else(或switch case)语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常 , 有多个操作包含这一相同的条件结构。 State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
优点
避免了过多的 swith…case 或者 if..else 语句的使用,避免了程序的复杂性
很好的使用体现了开闭原则和单一职责原则,每个状态都是一个子类,你要增加状态就增加子类,你要修改状态,你只修改一个子类就可以了
封装性非常好,这也是状态模式的基本要求。状态变换放置到了类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的变换。
缺点
具体状态类可能会有很多个,不好管理。
状态模式在Javascript中的应用
我的理解
ConcreteState具体状态类有两个职责:处理本状态必须完成的任务;过渡到其他状态。
可以采自下而上的方法来实现状态类,即先实现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;
&nb
补充:web前端 , JavaScript ,
- 更多JAVA疑问解答:
- java怎么在线读取ftp服务器上的文件内容
- 关于程序员的职业规划
- HTML和JSP矛盾吗?
- java小程序如何打包?
- java怎么split路径文件名?
- jsp+javaBean中Column 'ordersPrice' specified twice的错误
- Java TCP/IP Socket网络编程系列
- 大家来讨论一下我到底该用什么好?Swing 还是 JavaFX
- 关于Hibernate实体自身多对一的抓取问题
- 关于apache2+tomcat群集出现的问题
- spring 获取上下文问题
- SSH 导入导出excel 谁有这块的资料吗?
- Ext TreePanel 刷新问题
- springmvc 加载一个jsp页面执行多个方法 报404
- checkbox数组action怎么向页面传值