轻松掌握: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 ...
随机推荐
- 【目录】微软Infer.NET机器学习组件文章目录
本博客所有文章分类的总目录链接:http://www.cnblogs.com/asxinyu/p/4288836.html 1.微软Infer.NET机器学习组件目录 1. Infer.NET连载(一 ...
- UML学习总结
UML中的4+1模型 UML的4+1模型是一个叫Kruchten的人发明的,但网上还有其它版本的4+1 模型:Use case view, Logic view, Process view, Impe ...
- Tools - VirtualBox
为CentOS虚拟机安装增强功能 启动CentOS虚拟机,点击"菜单 -> 设备 -> 安装增强功能". vboxadd的映像文件将会被挂载到虚拟机,在桌面也可以看到, ...
- Theano入门神经网络(二) 实现一个XOR门
与非门的图片如下 示意图 详细解释: 1 定义变量的代码,包括了输入.权值.输出等.其中激活函数采用的是sigmod函数 # -*- coding: utf-8 -*- __author__ = 'A ...
- CSS3点点滴滴
css查遗补漏 标签(空格分隔): css 如果值为若干单词,则要给值加引号.p {font-family: "sans serif";} body的字体有继承兼容性问题,通常这么 ...
- 三、BLE(上)
1. BLE 1.1 模块构成与结构体层次关系 如上图所示,BLE模块有独立的application layer,这是因为该模块可以直接从BlueCore接收数据(通过GATT模 ...
- ROS 不能再详细的安装教程
版权声明:本文为博主原创文章,转载请标明出处: http://www.cnblogs.com/liu-fa/p/5779206.html 关于ROS(Robot OS 机器人操作系统),估计看这个博文 ...
- 【原创】Kakfa network包源代码分析
kafka.network包主要为kafka提供网络服务,通常不包含具体的逻辑,都是一些最基本的网络服务组件.其中比较重要的是Receive.Send和Handler.Receive和Send封装了底 ...
- 使用CKplayer插件在网页中嵌入视频的方法(常用笔记2)
在做网站中有时候我们需要在网页中嵌入视频,一般视频嵌入有以下几种方法: 1. 优酷代码嵌入 优点:简单,方便,可靠. 缺点:有广告,现在的网站非常注重用户体验,如果打开一个在线视频是有长广告的一定会崩 ...
- WCF双工通讯以及客户端间的间接通讯
由于学习计划安排不当,对WCF的认知一直停滞不前,最近工作上又用回了WCF,重拾一下,看到蒋老师介绍双工通讯的博文,实践一下,积累一下.原想着WCF的双工通讯就是原本的客户端能调用服务端的方法之余,服 ...