js 设计模式——状态模式
状态模式
允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。
简单的解释一下:
- 第一部分的意思是将状态封装成独立的类,并将请求委托给当前的状态对象,当对象的内部状态改变时,会带来不同的行为变化。
- 第二部分是从客户的角度来看,我们使用的对象,在不同的状态下具有截然不同的行为,这个对象看起来是从不同的类中实例化而来的,实际上这是使用了委托的效果。
现在举一个网上比较多的例子,没错就是电灯的例子(不要烦,请耐心往下看)
// 首先定义了一个Light类
class Light {
// 定义一个状态变量
constructor(){
this.state = 'off'
}
// 定义一个改变状态的方法
change(){
if(this.state === 'off'){
console.log('开灯')
this.state = 'on'
} else {
console.log('关灯')
this.state = 'off'
}
}
}
// 创建实例
let light = new Light()
// 调用方法
light.change()
当当当当,到此我们已经编写了一个状态机,逻辑简单又缜密,看起来还有那么点无懈可击。BUT,你懂的事实并非如此,人生也没那么多的如意。随着人类的进步,需求也不(de) 断(cuo) 进(jin) 步(chi)(●'◡'●),于是新的电灯出现了,这电灯可厉害了,第一次点击弱光,再次点击强光,再点七彩光,再点emmm关了。
按我们上面的逻辑来写,那可就刺激了:
- 首先违反了开闭原则,每次改动都要更改change()方法,使得方法变得不稳定
- 状态切换的不明显,无法一目了然的明白一共有多少种状态
- 状态之间的切换关系,不过是往change()方法里添加if、else语句,是change()方法更加难阅读和维护
那怎么办呢?有首歌怎么唱来着“新的电灯已经出现,怎么能够停滞不前”,哈哈,所以状态模式来了~~~
因为电灯的例子太无聊了,所以我换了一个例子但是呢意思是一样滴:
// 单曲循环类
class SingleCycle{
constructor(self){
this._self = self
}
modeSwitch(){
console.log('现在是单曲循环')
this._self.setState( this._self.listCirculation )
}
}
// 列表循环类
class ListCirculation{
constructor(self){
this._self = self
}
modeSwitch(){
console.log('现在是列表循环')
this._self.setState( this._self.sequentialPlay )
}
}
// 顺序播放类
class SequentialPlay{
constructor(self){
this._self = self
}
modeSwitch(){
console.log('现在是顺序播放')
this._self.setState( this._self.shufflePlay )
}
}
// 随机播放类
class ShufflePlay{
constructor(self){
this._self = self
}
modeSwitch(){
console.log('现在是随机播放')
this._self.setState( this._self.singleCycle )
}
}
// 音乐类
class Music{
constructor(){
// 为每个状态都创建一个状态对象
this.singleCycle = new SingleCycle(this)
this.listCirculation = new ListCirculation(this)
this.sequentialPlay = new SequentialPlay(this)
this.shufflePlay = new ShufflePlay(this)
// 定义初始状态为顺序播放
this.currState = this.sequentialPlay
}
// 切换播放模式
changeMode(){
this.currState.modeSwitch()
}
// 下一次点击时的播放状态
setState(newState){
this.currState = newState;
}
}
// 实例化音乐类
let music = new Music()
// 调用切换播放模式方法
music.changeMode()
好了,到此我们改编完成,如果你没有懵掉,good,如果你懵掉了,往下看:
- 首先我们定义了4个状态类
SingleCycle(单曲循环)、ListCirculation(列表循环)、SequentialPlay(顺序播放)、ShufflePlay(随机播放) - 每个状态类都定义了一个变量
_self来接收Music(音乐类)传过来的this,还有一个方法modeSwitch(状态更改),用来改变下一次要播放的状态 - 然后定义了一个
Music(音乐类),首先在里面为每一个状态都创建了一个状态对象,还定义了一个变量currState来记录下一次点击时的状态。 - 最后就是Music(音乐类)里面定义的两种方法
changeMode(切换播放模式)、setState(下一次点击时的播放状态)。当我们点击切换模式的时候,在changeMode(切换播放模式)中去调用之前定义好的状态类中的modeSwitch(状态更改)方法,完成模式切换的同时调用Music(音乐类)中的setState(下一次点击时的播放状态)方法来对状态进行改变,保证下一次点击时切换不同的模式。
通过上面的方法可以看出:
- 我们可以在
Music(音乐类)中清楚的知道一共有多少个状态,同时Music(音乐类)中不再进行任何实质性的操作,而是通过this.currState.modeSwitch()交给了当前持有的状态对象去执行 - 状态的切换规律被事先在每一个状态类中定义好了,在
Music(音乐类)中没有任何一个和状态切换相关的条件分支语句
悄悄地说,上面的方法还阔以再完美一点呦
小小的拓展
通过上面的介绍我们了解到了每一个状态类都有一个 modeSwitch() 方法,也就意味着我们每次添加状态类都要写一个方法,问题来了,人非圣贤,孰能无过?所以咧难免会丢掉的嘛!
然后做一些小小的优化:
// 定义一个State类
class State{
constructor(self){
this._self = self
}
modeSwitch(){
throw new Error( '父类的 modeSwitch 方法必须被重写' )
}
}
// 状态类(举一个为例)
// 单曲循环类(继承State类)
class SingleCycle extends State{
modeSwitch(){
console.log('现在是单曲循环')
this._self.setState( this._self.listCirculation )
}
}
好了完成,当某一天我们忘了写方法,也能够快速的定位到错误
目前对于状态模式的理解就这么多,以后有了新的理解会继续更新的,溜了溜了(~ ̄▽ ̄)~
js 设计模式——状态模式的更多相关文章
- 14. 星际争霸之php设计模式--状态模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- [Head First设计模式]生活中学设计模式——状态模式
系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...
- JAVA 设计模式 状态模式
用途 状态模式 (State) 当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 状态模式是一种行为型模式. 结构
- 深入浅出设计模式——状态模式(State Pattern)
模式动机 在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的 (stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的.当一个这样的 ...
- C++设计模式——状态模式
前言 在实际开发中,我们经常会遇到这种情况:一个对象有多种状态,在每一个状态下,都会有不同的行为.那么在代码中我们经常是这样实现的. typedef enum tagState { state, st ...
- C#设计模式--状态模式
设计模式: 状态模式(State Pattern) 简单介绍: 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式. 在状态模式中,我们创建表示 ...
- Java设计模式—状态模式
状态模式又是一个比较难的设计模式 定义如下: 当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类. 个人理解:通俗的讲,状态模式就是状态的改变引起了行为的改变,但是,我们只能看到行为的 ...
- 设计模式-状态模式(State Pattern)
本文由@呆代待殆原创,转载请注明出处:http://www.cnblogs.com/coffeeSS/ 状态模式简介 状态模式允许一个对象在其内部状态改变的时候改变它的行为,他的内部会存着好几种状态, ...
- JavaScript设计模式——状态模式
状态和行为: 所谓对象的状态,通常指的就是对象实例的属性的值:而行为指的就是对象的功能,再具体点说,行为大多可以对应到方法上. 状态模式的功能就是分离状态的行为,通过维护状态的变化,来调用不同状态对应 ...
随机推荐
- 【HDU - 3533】Escape(bfs)
Escape Descriptions: 一个人从(0,0)跑到(n,m),只有k点能量,一秒消耗一点,在图中有k个炮塔,给出炮塔的射击方向c,射击间隔t,子弹速度v,坐标x,y问这个人能不能安全到 ...
- 手机web app开发笔记
各位朋友好,最近自学开发了一个手机Web APP,“编程之路”,主要功能包括文章的展示,留言,注册登录,音乐播放等.为了记录学习心得,提高自己的编程水平,也许对其他朋友有点启发,特整理开发笔记如下. ...
- TensorFlow笔记-模型的保存,恢复,实现线性回归
模型的保存 tf.train.Saver(var_list=None,max_to_keep=5) •var_list:指定将要保存和还原的变量.它可以作为一个 dict或一个列表传递. •max_t ...
- 从后端到前端之Vue(四)小试牛刀——真实项目的应用(树、tab、数据列表和分页)
学以致用嘛,学了这么多,在真实项目里面怎么应用呢?带着问题去学习才是最快的学习方式.还是以前的那个项目,前后端分离,现在把前端换成vue的,暂时采用脚本化的方式,然后在尝试工程化的方式. 现在先实现功 ...
- 盘一盘 synchronized (一)—— 从打印Java对象头说起
Java对象头的组成 Java对象的对象头由 mark word 和 klass pointer 两部分组成, mark word存储了同步状态.标识.hashcode.GC状态等等. klass ...
- 盘一盘 synchronized (二)—— 偏向锁批量重偏向与批量撤销
在本文讲解之前,先来简单了解一下为什么会有批量重偏向和批量撤销. 批量重偏向:当一个线程创建了大量对象并执行了初始的同步操作,后来另一个线程也来将这些对象作为锁对象进行操作,会导偏向锁重偏向的操作 ...
- DH、RSA与ElGamal非对称加密算法实现及应用
1.对称加密与非对称加密概述 关于对称加密与非对称加密的概念这里不再多说,感兴趣可以看下我之前的几篇文章,下面说一说两者的主要区别. 对称加密算法数据安全,密钥管理复杂,密钥传递过程复杂,存在密钥泄露 ...
- JAVA从零学习 第一天 邮箱ych1102@163.com QQ382993199
学习编程 听说读写 寻寻渐进 要准备好长期蒙蒙的状态 延迟3个月后明白 机器语言 二级制 1010 1100 0011 汇编语言 助记词表达程序 机器如果执行就需要编译 汇编语言移植性 ...
- Django使用本机IP无法访问,使用127.0.0.1能正常访问
使用Django搭建web站点后,使用127.0.0.1能访问,但是用自己本机IP却无法访问. 我们先到Django项目中找到setting文件 找到——> ALLOWED_HOSTS = [] ...
- 【iOS】NSLog 打印 BOOL 类型值
这个问题以前没在意,刚偶然打印,发现有些问题,上网查了下,发现是这么搞的: NSLog(@"%@", isEqual?@"YES":@"NO" ...