轻松掌握:JavaScript状态模式
状态模式
状态模式(State)允许一个对象在其内部状态改变的时候改变它的行为,对象看起来似乎修改了它的类。
状态模式的使用场景也特别明确,有如下两点:
一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。(有些对象通常会有好几个状态,在每个状态都只可以做当前状态才可以做的事情,而不能做其它状态能做的事儿)
一个操作中含有大量的分支语句,而且这些分支语句依赖于该对象的状态。状态通常为一个或多个枚举常量的表示。
一、有限状态机
- 状态总数(state)是有限的。
- 任一时刻,只处在一种状态之中。
- 某种条件下,会从一种状态转变(transition)到另一种状态。
通用做法:将状态封装成独立的类(状态机),并将请求委托给当前的状态对象,当对象的内部状态发生改变时,会带来不同的行为变化。
二、性能优化点
- 如何管理状态对象的创建和销毁?第一种仅当state对象被需要时才创建并随后销毁(state对象比较庞大,优先选择), 另一种是一开始就创建好所有的状态对象,并且始终不销毁它们(状态改变频繁)。
- 利用享元模式共享一个state对象。
举个稍微复杂的例子,相信大家都玩过角色扮演类游戏,里面的角色就有很多种状态(站、走、跑、跳、蹲等),各个状态之间的切换是被规定好了的,且任何时刻都只能处于一种状态中,而在每个状态下,角色只能做当前状态下被允许的行为(如:普通攻击、各种技能攻击、防御等)
这是我写的移动小球的例子:
#div{
position: absolute;
width: 80%;
height: 80%;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
border: 1px solid darkcyan;
}
#go{
position:absolute;
width:50px;
height:50px;
left: 10px;
top:20px;
border:1px solid gray;
-webkit-border-radius : 50px;
-moz-border-radius: 50px;
border-radius: 50px;
background-image: radial-gradient(circle, white 5%, black 100%);
}
三、JavaScript版本的状态机(以简单的开关灯为例)
1.通过Function.prototype.call方法直接把请求委托给某个字面量对象来执行
// 状态机
var FSM = {
off: {
buttonWasPressed: function() {
console.log("关灯");
this.button.innerHTML = "下一次按我是开灯"; // 这是Light上的属性!!!
this.currState = FSM.on; // 这是Light上的属性!!!
}
},
on: {
buttonWasPressed: function() {
console.log("开灯");
this.button.innerHTML = "下一次按我是关灯";
this.currState = FSM.off;
}
},
};
var Light = function() {
this.currState = FSM.off; // 设置当前状态
this.button = null;
};
Light.prototype.init = function() {
var button = document.createElement("button");
self = this;
button.innerHTML = "已关灯";
this.button = document.body.appendChild(button);
this.button.onclick = function() {
// 请求委托给FSM状态机
self.currState.buttonWasPressed.call(self);
}
}
var light = new Light();
light.init();
2.利用delegate函数
var delegate = function(client, delegation) {
return {
buttonWasPressed: function() {
return delegation.buttonWasPressed.apply(client, arguments);
}
};
};
// 状态机
var FSM = {
off: {
buttonWasPressed: function() {
console.log("关灯");
this.button.innerHTML = "下一次按我是开灯";
this.currState = this.onState;
}
},
on: {
buttonWasPressed: function() {
console.log("开灯");
this.button.innerHTML = "下一次按我是关灯";
this.currState = this.offState;
}
},
};
var Light = function() {
this.offState = delegate(this, FSM.off);
this.onState = delegate(this, FSM.on);
this.currState = this.offState; // 设置当前状态
this.button = null;
};
Light.prototype.init = function() {
var button = document.createElement("button");
self = this;
button.innerHTML = "已关灯";
this.button = document.body.appendChild(button);
this.button.onclick = function() {
// 请求委托给FSM状态机
self.currState.buttonWasPressed();
}
}
var light = new Light();
light.init();
状态模式和策略模式很像,它们都封装了一系列的算法或行为,它们都有一个上下文对象来把请求委托给封装类(策略类、状态机),但它们的意图不同:
- 策略类的各个属性之间是平等平行的,它们之间没有任何联系
- 状态机中的各个状态之间存在相互切换,且是被规定好了的。
参考文献: 《JavaScript模式》 《JavaScript设计模式与开发实践》
轻松掌握:JavaScript状态模式的更多相关文章
- JavaScript状态模式及状态机模型
这是一篇,我自己都看不完的文章... 文章大体就两部分: 状态模式的介绍 状态机模型的函数库javascript-state-machine的用法和源码解析 场景及问题背景: 我们平时开发时本质上就是 ...
- javascript - 状态模式 - 简化分支判断流程
状态模式笔记 当一个对象的内部状态发生改变时,会导致行为的改变,这像是改变了对象 状态模式既是解决程序中臃肿的分支判断语句问题,将每个分支转化为一种状态独立出来,方便每种状态的管理又不至于每次 ...
- Javascript设计模式之我见:状态模式
大家好!本文介绍状态模式及其在Javascript中的应用. 模式介绍 定义 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式主要解决的是控制一个对象状态的条件表达式 ...
- javascript设计模式学习之十六——状态模式
一.状态模式的定义 状态模式的关键是区分事务内部和外部的状态,事务内部状态改变往往会带来事务的行为改变. 状态模式中有意思的一点是,一般我们谈到封装,都是优先封装对象的行为,而非对象的状态.但在状态模 ...
- 再起航,我的学习笔记之JavaScript设计模式19(状态模式)
状态模式 概念介绍 状态模式(State):当一个对象的内部状态发生改变时,会导致其行为的改变,这看起来像是改变了对象 示例演示 在我们写项目的过程中或多或少会遇到如下的多分支判断 function ...
- JavaScript设计模式 - 状态模式
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 深入理解JavaScript系列(43):设计模式之状态模式
介绍 状态模式(State)允许一个对象在其内部状态改变的时候改变它的行为,对象看起来似乎修改了它的类. 正文 举个例子,就比如我们平时在下载东西,通常就会有好几个状态,比如准备状态(ReadySta ...
- JavaScript设计模式——状态模式
状态和行为: 所谓对象的状态,通常指的就是对象实例的属性的值:而行为指的就是对象的功能,再具体点说,行为大多可以对应到方法上. 状态模式的功能就是分离状态的行为,通过维护状态的变化,来调用不同状态对应 ...
- javascript设计模式--状态模式(State)
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
随机推荐
- 在WPF应用程序中利用IEditableObject接口实现可撤销编辑的对象
这是我辅导的一个项目开发中的例子,他们是用WPF做界面开发,在学习了如何使用MVVM来实现界面与逻辑的分离,并且很好的数据更新之后,有一个疑问就是,这种双向的数据更新确实很不错,但如果我们希望用户可以 ...
- JavaScript获取图片的原始尺寸
页面里的img元素,想要获取它的原始尺寸,以宽度为例可能首先想到的就是width,如下 <img src="http://img11.360buyimg.com/da/g14/M07/ ...
- JavaScript作用域原理(一)——作用域链
一.作用域的描述 JavaScript权威指南中对作用域有一句很精辟的描述:“JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里.” 在JavaScript中,作用域的 ...
- HTML5移动Web开发(三)——在移动网站中使用HTML5
创建一个简单得HTML5页面ch01e2.html <html> <head> <meta name="viewport" content=" ...
- [Python] Ubuntu12.04LTS
Ubuntu 12.04LTS中缺省安装了Python2.7.3. python -h 查看可用选项 python -V 查看Python版本 下面写个简单的测试程序: 新建HelloWorld.py ...
- select查询时,如何把指定的行放置在最前面
可以用case when做一个列,然后根据这个列来排序,下面给出代码 ' end) as 'abc' from table order by abc
- APP账号密码传输安全分析
最近在搞公司的安卓APP测试(ThinkDrive 企邮云网盘)测试,安卓app测试时使用代理抓包,发现所此app使用HTTP传输账号密码,且密码只是普通MD5加密,存在安全隐患,无法 ...
- 单纯形方法(Simplex Method)
最近在上最优理论这门课,刚开始是线性规划部分,主要的方法就是单纯形方法,学完之后做了一下大M算法和分段法的仿真,拿出来与大家分享一下.单纯形方法是求解线性规划问题的一种基本方法. 线性规划就是在一系列 ...
- HTML5实现3D和2D可视化QuadTree四叉树碰撞检测
QuadTree四叉树顾名思义就是树状的数据结构,其每个节点有四个孩子节点,可将二维平面递归分割子区域.QuadTree常用于空间数据库索引,3D的椎体可见区域裁剪,甚至图片分析处理,我们今天介绍的是 ...
- 纯Shading Language绘制HTML5时钟
今天是2014年的最后一天,这个时刻总会让人想起时钟,再过几个小时地球人都要再老了一岁,于是搞个HTML5版的时钟就是我们今天要完成的任务,实现HTML5的时钟绘制一般会采用三种方式,第一种采用CSS ...