首页 > JS设计模式(13)状态模式

JS设计模式(13)状态模式

什么是状态模式?

定义:将事物内部的每个状态分别封装成类,内部状态改变会产生不同行为。

主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。

何时使用:代码中包含大量与对象状态有关的条件语句。

如何解决:将各种具体的状态类抽象出来。

应用实例: 1、打篮球的时候运动员可以有正常状态、不正常状态和超常状态。 2、曾侯乙编钟中,'钟是抽象接口','钟A'等是具体状态,'曾侯乙编钟'是具体环境(Context)。

优点: 1、封装了转换规则。 2、枚举可能的状态,在枚举状态之前需要确定状态种类。 3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。 5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点: 1、状态模式的使用必然会增加系统类和对象的个数。 2、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。 3、状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

使用场景: 1、行为随状态改变而改变的场景。 2、条件、分支语句的代替者。

注意事项:在行为受状态约束的时候使用状态模式,而且状态不超过 5 个。

 

场景 demo

某某牌电灯,按一下按钮打开弱光,按两下按钮打开强光,按三下按钮关闭灯光。

// 将状态封装成不同类
const weakLight = function(light) {this.light = light
}weakLight.prototype.press = function() {console.log('打开强光')this.light.setState(this.light.strongLight)
}const strongLight = function(light) {this.light = light
}strongLight.prototype.press = function() {console.log('关灯')this.light.setState(this.light.offLight)
}const offLight = function(light) {this.light = light
}offLight.prototype.press = function() {console.log('打开弱光')this.light.setState(this.light.weakLight)
}const Light = function() {this.weakLight = new weakLight(this)this.strongLight = new strongLight(this)this.offLight = new offLight(this)this.currentState = this.offLight          // 初始状态
}Light.prototype.init = function() {const btn = document.createElement('button')btn.innerHTML = '按钮'document.body.append(btn)const self = thisbtn.addEventListener('click', function() {self.currentState.press()})
}Light.prototype.setState = function(state) { // 改变当前状态this.currentState = state
}const light = new Light()
light.init()// 打开弱光
// 打开强光
// 关灯

 

非面向对象实现的状态模式

借助于 JavaScript 的委托机制,可以像如下实现状态模式:

const obj = {'weakLight': {press: function() {console.log('打开强光')this.currentState = obj.strongLight}},'strongLight': {press: function() {console.log('关灯')this.currentState = obj.offLight}},'offLight': {press: function() {console.log('打开弱光')this.currentState = obj.weakLight}},
}const Light = function() {this.currentState = obj.offLight
}Light.prototype.init = function() {const btn = document.createElement('button')btn.innerHTML = '按钮'document.body.append(btn)const self = thisbtn.addEventListener('click', function() {self.currentState.press.call(self) // 通过 call 完成委托
  })
}const light = new Light()
light.init()

 

转载于:https://www.cnblogs.com/wuguanglin/p/StatePattern.html

更多相关:

  • 关于如何在有噪声的数据中进行状态估计的问题的理解,状态估计的问题是指在运动和观测方程中,通常假设两个噪声ωiomega_i和υk,jupsilon_{k,j}满足零均值的高斯分布, xk=f(xk−1,uk)+ωkx_k=f(x_{k-1},u_k)+omega_k其中ωk→N(0,Rk)omega_k ightarro...

  • 强化学习(英语:Reinforcement learning,简称RL)是机器学习中的一个领域,强调如何基于环境而行动,以取得最大化的预期利益。其灵感来源于心理学中的行为主义理论,即有机体如何在环境给予的奖励或惩罚的刺激下,逐步形成对刺激的预期,产生能获得最大利益的习惯性行为。这个方法具有普适性,因此在其他许多领域都有研究,例如博弈...

  • 文章目录PG 的状态机和peering过程1. PG 状态机变化的时机2. pg的状态演化过程3. pg状态变化实例讲解3.1 pg状态的管理结构3.2 数据的pg状态变化过程3.2.1 NULL -> initial3.2.2 initial -> reset -> Started3.2.3 Started(start) ->St...

  • 别小看这个功能, 感觉在写一些技术 Blog 的情况下还是挺有用的.   打开QQ拼音: 输入法设置->基本设置->初始状态->中文状态下使用英文标点.  转载于:https://www.cnblogs.com/qrlozte/p/4904087.html...

  •   /*禁止缩放safari浏览器*/ var scale = {disabledSafari: function () {/* 阻止双击放大*/var lastTouchEnd = 0;document.addEventListener("touchstart", function (event) {if (event.touch...

  •   $g.$utils = {/**舒工Ajax-lite 1.0 -- 最精简的ajax自定义访问方法*/ajax: function (o) {var p = o.post, g = o.get, d = p.data, a = p.async, J = 'json', j = p[J], s = g.success, e =...

  •   Sg.js框架核心概念: 1)所有变量、方法、类对象全部都是从属于$g主树,由$g分支出很多$g.变量名、$g.方法、$g.对象id、$g.类;2)获取控件内部属性必须使用公开的get方法获取,禁止直接用访问内部变量方式来获取控件内部变量、属性值;3)修改控件内部属性、绑定方法等都必须使用公开的set方法来操作,禁止直接用访问...

  •  一、ios header导航栏被推起解决方法 1 设置弹出软键盘时自动改变webview的高度 plus.webview.currentWebview().setStyle({ softinputMode: "adjustResize" // 弹出软键盘时自动改变webview的高度 }); 2 增加样式 html...

  • 前端发送Ajax请求到服务器,服务器返回数据这一过程,因原因不同耗时长短也有差别,且这段时间内页面显示空白。如何优化这段时间内的交互体验,以及长时间内服务器仍未返回数据这一问题,是我们开发中不容忽视的重点。 常见的做法是: 1、设置超时时间,一旦时间超过设定值,便终止请求;2、页面内容加载之前,手动增加一个 loading 层。 代码...

  • mutable的中文意思是“可变的,易变的”,跟constant(既C++中的const)是反义词。   在C++中,mutable也是为了突破const的限制而设置的。被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中。   我们知道,如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成cons...

  • 前言:很多人都把const int * 、int * const、int const* 的区别和联系搞混,我自己在学习C++的过程中,也经常性          弄不 清楚,今天特意总结一下,作为学习笔记记录下来。 一,const修饰符用于指针         将const用于指针有些很微妙的地方,有两种不同的方式将const关键...

  •   注意,前情提示: 本代码基于《Node.js(nodejs)对本地JSON文件进行增、删、改、查操作(轻车熟路)》 传送门Node.js(nodejs)对本地JSON文件进行增、删、改、查操作(轻车熟路)_你挚爱的强哥❤给你发来1条消息❤-CSDN博客   在/api/demo/文件夹下面创建exportAndDownl...

  • 项目结构 main.js(入口文件,开启9999端口监听,实现RESTful风格接口访问) const express = require("express"); const app = express(); const port = 9999;//设置端口号,如果端口号被占用需要自己修改,否则无法跑起来(建议不要用80和80...

  • ES6 你可能不知道的事 – 基础篇 转载 作者:淘宝前端团队(FED)- 化辰 链接:taobaofed.org/blog/2016/07/22/es6-basics/   序   ES6,或许应该叫 ES2015(2015 年 6 月正式发布),对于大多数前端同学都不陌生。   首先这篇文章不是工具书,不会去过多谈概念,而是...