本回内容介绍

上一回聊了聊组合模式(Composite),用组合模式模拟了个图片库,聊了递归。
介一回聊状态模式(State),官方描述允许一个对象在其内部状态改变时改变它的行为。略抽象,不过看了代码会觉得比较简单,直接看代码先。

1. 状态模式

状态模式中引入了抽象状态类和具体状态类,这里会用到之前讲过的接口模式,不清楚的盆友可以看系列05,这个例子是我根据一段PHP的状态模式代码改的JS版本,如下:

var c = console,d = document;
window.onload = function(){// 定义了一个state接口,俩方法handle,displayvar State = new Interface("State",["handle","display"]);// 这里的Context是环境类,或者称为上下文类,是拥有多种状态的对象。var Context = function(state){// 状态变化的属性var _state = null;var _self = this;// 这里是设置状态对象this.setState = function(state){_self._state = state;}// 调用状态对象的方法  this.request = function(){_self._state.display();_self._state.handle(_self);}this.setState(state);}// 具体状态类,抽象状态类的子类var StateA = function(){// 检测接口,不明白的童鞋看系列05Interface.ensureImplements(this,State);}// 状态类的实现StateA.prototype = {constructor:StateA,// 这里的context指向的是Contexthandle:function(context){// 设置为其他状态context.setState(new StateB());},// 具体实现的方法display:function(){c.log('StateA');}}// StateB跟StateA一样,只是状态设置不同var StateB = function(){    Interface.ensureImplements(this,State);}StateB.prototype = {constructor:StateB,handle:function(context){context.setState(new StateC());},display:function(){c.log('StateB');}}// StateC跟StateB一样,只是状态设置不同var StateC = function(){    Interface.ensureImplements(this,State);}StateC.prototype = {constructor:StateC,handle:function(context){context.setState(new StateA());},display:function(){c.log('StateC');}}// 测试代码var o = new Context(new StateB());o.request();    // StateBo.request();    // StateCo.request();    // StateAo.request();    // StateBo.request();    // StateCo.request();    // StateA
} 

之所以把这个例子改成JS版本,是因为这个例子比较简单,直观。在实际使用时,在一个状态类中可能包含多个业务方法,如果在具体状态类中某些业务方法的实现完全相同,可以将这些方法移至抽象状态类,实现代码的复用。

2. 状态模式之工作流

状态模式在工作流或游戏等各种系统中应用比较广泛,下面的例子是一个简单的订单审批流程,根据一段Java的状态模式代码改的JS版本,如下:

var c = console,w = window;
w.onload = function(){// 业务申请方function Obj() {// 申请方this.obj = '';// 日期this.sDate = '';// 金额this.aMount = '';// 结果this.res = '';}// 跟上一个例子一样,Context状态管理类var Context = function (s) {this.state = null;this.run = function (s) {this.state = s;};this.run(s);}// 第一层级审核var StateA = function (o) {// 这一堆就是一个简单交互var reply = w.prompt('同意请按1,不同意请按任意键');var res = reply == 1 ? '同意' : '不同意';var state;o.res = res;// 一堆打印信息c.log('平台审核中...' + '申请方:' + o.obj + ' ' + '日期:' + o.sDate + ' ' + '金额:' + o.aMount + ' ' + '平台审核结果:' + o.res);// 判断是否同意,如果不同意直接走Notice提示不同意if (reply == 1) {// 这里就是走第二层级state = new StateB(o);} else {state = new Notice(o);}return state;}// 第二层级审核,跟第一层级差不多var StateB = function (o) {var reply = w.prompt('同意请按1,不同意请按任意键');var res = reply == 1 ? '同意' : '不同意';var state;o.res = res;c.log('商家审核中...' + '申请方:' + o.obj + ' ' + '日期:' + o.sDate + ' ' + '金额:' + o.aMount + ' ' + '商家审核结果:' + o.res);// 因为是最终审核,所以直接走Notice提示state = new Notice(o);return state;}// Notice通知类,打印信息var Notice = function (o) {c.log('申请方:' + o.obj + '的流程结束,审核结果为:' + o.res);}// 测试var o = new Obj();o.obj = '大卫';o.sDate = '圣诞节';o.aMount = 250;var req = new Context(new StateA(o));req.run();
}; 

这个例子跟上一个例子都是状态模式的一个很好体现,这个例子更贴近实际开发,
申请方提交订单,平台订单审核,审核通过更改状态为审核通过,然后继续商家中心审核,通过与不通过都流程结束,直接调用提示类提示结果。

3. 有限状态机

有限状态机(Finite-state machine)是一个非常有用的模型,可以模拟世界上大部分事物。这个是官方说法,简单说,她有三个特征:
1,状态总数(state)是有限的。
2,任一时刻,只处在一种状态之中。
3,某种条件下,会从一种状态转变(transition)到另一种状态。
直接代码吧,很直观的,根据网上的交通灯例子改的,如下::

var c = console,d = document;
window.onload = function(){var Light = function() {// 设置默认状态,关灯this.currentState = State.off;this.lightSwitch = null;};Light.prototype.run = function() {var _self = this;// 这里是开关var lightSwitch = d.createElement('button');// 这个canvas就当是一盏灯了var cvs = d.createElement('canvas');cvs.width = '200';cvs.height = '200';cvs.style.backgroundColor = 'lightblue';cvs.style.borderRadius = '50%';cvs.style.display = 'block';// 初始值是开灯lightSwitch.innerHTML = '开灯';// Dom方法appendChild没什么好说的this.lightSwitch = d.body.appendChild(lightSwitch);this.cvs = d.body.appendChild(cvs);// 开关的点击事件this.lightSwitch.onclick = function() {// 委托请求给State状态机,这里分两步走,第一步是_self.currentState,第二步是btnPress,call用来指向将作用域指向本身_self.currentState.btnPress.call(_self);};};// 这里就是多种状态间的切换,这里只写了两种,开关灯var State = {off: {btnPress: function() {this.lightSwitch.innerHTML = '关灯';this.cvs.style.display = 'none';this.currentState = State.on;}},on: {btnPress: function() {this.lightSwitch.innerHTML = '开灯';this.cvs.style.display = 'block';this.currentState = State.off;}}};// 测试代码var light = new Light();light.run();
};

这里就是多种状态间的切换,这里只写了两种,开关灯,好玩儿一点可以换canvas的颜色,做变亮变暗的状态。


装个逼,虽然最近热映的《寻龙诀》好看,还是要推荐一个阿汤哥的老电影《遗忘战境》~~

这一回聊的状态模式,有限状态机,状态模式可以允许客户端改变状态的转换行为,而状态机则是能够自动改变状态~。
下面的内容,聊一下状态管理,这里拿一个极具审美(因为作者经常提审美^_^)的JS库Vue.js的官方例子来说。

JS状态管理

Vue官方解释是集中管理状态更易于理解状态将怎样变化。组件仍然可以拥有和管理它的私有状态。看过上面的例子,看这个应该很好理解,继续写:

// 这里的store里面放了所有的action
var store = {state: {message: 'Hello!'},// 这里的action则用来修改store的状态stateactionA: function () {this.state.message = 'action A triggered'},// 这里跟上面的例子很像actionB: function () {this.state.message = 'action B triggered'}
}
// 这个new Vue暂时不用管,简单的解释下吧,通过构造函数Vue创建一个Vue的根实例
var vmA = new Vue({data: {privateState: {},sharedState: store.state}
})var vmB = new Vue({data: {privateState: {},sharedState: store.state}
})

这是vue.js官网上的一个例子,最近很火的框架react,vue.js在说flux单向数据流,其实就是在维护状态。

话外音

这里啰嗦一下,有盆友建议说聊一下AngularJS,在系列04里有聊过一点点ng1.x的源码,也模拟了一下,并且说过可以的话,分享读过的Angularjs源码段子。介于前端框架风起云涌,其实,对Angular有兴趣的盆友,可以直接从Angular2开始,如果是学习源码的话,Vue.js的源码读起来会更有美感(因为作者反复提审美^_^)~~

这一回,主要聊了状态模式,有限状态机,介绍了下Vue.js这个库。
下一回,聊一聊JS的链式调用,没错,肯定会模拟框架,库什么的。

客观看完点个赞,推荐推荐呗,嘿嘿~~


注:此系飞狐原创,转载请注明出处

听飞狐聊JavaScript设计模式系列13相关推荐

  1. 听飞狐聊JavaScript设计模式系列11

    本回内容介绍 上一回,聊了适配器模式,图片预加载,介一回,聊桥接模式(Bridge),跟之前一样,难度比较小,桥接模式将抽象部分与它的实现部分分离,通过桥接模式联系彼此,同时又使之都可以独立地变化.也 ...

  2. 听飞狐聊JavaScript设计模式系列05

    本回内容介绍 上一回聊到JS的类的模拟,继承,分析了nodejs,extjs,jquery,underscore的继承源码. 介一回,偶们来聊一下在JS中模拟接口,掺元类,装饰者模式,有些盆友可能用过 ...

  3. 听飞狐聊JavaScript设计模式系列07

    本回内容介绍 上一回聊到JS单例模式(singleton),做了一道题,内容不多,比较容易理解. 介一回嘞,聊聊工厂模式,之前聊到过工厂模式,这回聊深入点儿,可能会比较抽象,不过好在实际开发中使用还算 ...

  4. JavaScript设计模式系列—模式篇总结(上)

    转载请注明预见才能遇见的博客:http://my.csdn.net/ 原文地址:https://blog.csdn.net/pcaxb/article/details/102517956 JavaSc ...

  5. JavaScript设计模式系列四之外观模式(附案例源码)

    文章初衷 设计模式其实旨在解决语言本身存在的缺陷, 目前javaScript一些新的语法特性已经集成了一些设计模式的实现, 大家在写代码的时候,没必要为了用设计模式而去用设计模式, 那么我这边为什么还 ...

  6. javascript设计模式系列 - LukeLin - 博客园

    javascript设计模式系列 创建型: 1.抽象工厂模式(Abstract Factory) 2.构建者模式(Builder) 3.工厂方法模式(Factory Method) 4.原型模式(Pr ...

  7. javascript学习系列(13):数组中的concat方法

    最好的种树是十年前,其次是现在.歌谣 每天一个前端小知识 提醒你改好好学习了 知乎博主 csdn博主 b站博主  放弃很容易但是坚持一定很酷     我是歌谣 喜欢就一键三连咯 你得点赞是对歌谣最大的 ...

  8. javascript设计模式系列

    创建型: 1.抽象工厂模式(Abstract Factory) 2.构建者模式(Builder) 3.工厂方法模式(Factory Method) 4.原型模式(Prototype) 5.单例模式(S ...

  9. JavaScript设计模式之发布-订阅模式(观察者模式)-Part1

    <JavaScript设计模式与开发实践>读书笔记. 发布-订阅模式又叫观察者模式,它定义了对象之间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖它的对象都将得到通知. 例如 ...

最新文章

  1. Fibonacci数列时间复杂度之美妙
  2. 实验15:通过注解分别创建Dao、Service、Controller★
  3. ubuntu安装openssl命令
  4. [javascript] Date 时间精确到天
  5. 27 款经典的CSS 框架
  6. gin 前端文件打包_远程URL文件批量下载打包的方法
  7. php 实时监测网站是否异常_网站监控劫持问题,怎么通过网站监控解决劫持问题...
  8. 如何使用 HttpReports 监控 .NET Core 应用程序
  9. 第一百五十期:Java程序员必备:异常的十个关键知识点
  10. 湖北工业大学计算机专硕学费,2019年湖北工业大学硕士研究生学费奖助政策
  11. 苹果电脑 不能使用服务器发送邮件,解决Mac上无法使用的邮件问题的技术
  12. 不能bostype没有元数据异常_EAS BOS 开发问题集锦
  13. BIM工程信息管理新系统- 系统管理模块
  14. STM32工作笔记0060---窗口看门狗实验
  15. 探寻C++最快的读取文件的方案
  16. 003 第一个Python程序
  17. JavaWeb项目开发流程
  18. h3c无线控制器ac配置
  19. 如何更改计算机安全策略设置,用批处理更改本地安全策略
  20. 谷歌账号Gmail邮箱修改密码提示需要手机设备验证码如何处理

热门文章

  1. 模电(十)结型场效应管
  2. python扩展屏幕截图_Python实现屏幕截图的两种方式
  3. scholarscope不显示影响因子_帮研网—科研共享平台——新版Pubmed显示影响因子并设置筛选过滤器...
  4. Jconsole的使用及对java内存池的专业术语理解
  5. 机器学习中qa测试_机器学习项目测试怎么做?(看实例)
  6. 在ArcGIS中如何将A图层中的部分要素粘贴复制到B图层当中?
  7. ## ***电池SOC仿真系列-基于扩展卡尔曼(EKF)算法的SOC估计(内含代码等资料)***
  8. MindMaster-------ERP系统上线计划
  9. 阿里悄悄启动教育新基建
  10. pdm文件生成的几种方式