zoukankan      html  css  js  c++  java
  • Javascript-设计模式_状态模式

    状态模式

    前言

    状态模式的关键是区分事物内部的状态,事物内部状态的改变往往会带来事物的行为改变,即对象行为是基于状态来改变的,内部的状态转化,导致了行为表现形式不同

    当电灯开着,此时按下开关,电灯会切换到关闭状态;再按一次开关,电灯又将被打开。同一个开关在不同的状态下,表现出来的行为是不一样的

     

    场景条件--有限状态机

    • 状态总数(state)是有限的

    • 任一时刻,只处在一种状态之中

    • 某种条件下,会从一种状态转变(transition)到另一种状态

    允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类

    解释:

    • 将状态封装成独立的类,并将请求委托给当前的状态对象,当对象的内部状态发生改变时,会带来不同的行为变化

    • 使用的对象,在不同的状态下具有截然不同的行为(委托效果)

    谈到封装,一般优先考虑封装对象的行为,而不是对象的状态,但在状态模式中刚好相反,状态模式的关键是把事物的每种状态都封装成单独的类

     

    示例

    点灯程序 (弱光 –> 强光 –> 关灯)循环

    /* 关灯 */
    const OffLightState = light => {
        this.light = light
    }
    
    /* 弱光 */
    const WeakLightState = light => {
        this.light = light
    }
    
    /* 强光 */
    const StrongLightState = light => {
        this.light = light
    }
    
    const Light = () => {
        // 开关状态
        this.offLight = new OffLightState(this)
        this.weakLight = new WeakLightState(this)
        this.strongLight = new StrongLightState(this)
        // 快关按钮
        this.button = null
    }
    
    Light.prototype.init = () => {
        const button = document.createElement('button')
        const self = this
        this.button = document.body.appendChild(button)
        this.button.innerHTML = '开关'
        this.currentState = this.offLight
        this.button.click = () => {
            self.currentState.buttonWasPressed()
        }
    }
    
    /* 让抽象父类的抽象方法直接抛出一个异常(避免状态子类未实现buttonWasPressed方法) */
    Light.prototype.buttonWasPressed = () => {
        throw new Error('父类的buttonWasPressed方法必须被重写')
    }
    
    Light.prototype.setState = newState => {
        this.currentState = newState
    }
    
    /* 关灯 */
    OffLightState.prototype = new Light()  // 继承抽象类
    OffLightState.prototype.buttonWasPressed = () => {
        console.log('关灯!')
        this.light.setState(this.light.weakLight)
    }
    
    /* 弱光 */
    WeakLightState.prototype = new Light()
    WeakLightState.prototype.buttonWasPressed = () => {
        console.log('弱光!')
        this.light.setState(this.light.strongLight)
    }
    
    /* 强光 */
    StrongLightState.prototype = new Light()
    StrongLightState.prototype.buttonWasPressed = () => {
        console.log('强光!')
        this.light.setState(this.light.offLight)
    }
    

    性能优化点

    1. 如何管理状态对象的创建和销毁

      第一种仅当state对象被需要时才创建并随后销毁(state对象比较庞大,优先选择)

      另一种是一开始就创建好所有的状态对象,并且始终不销毁它们(状态改变频繁)

    2. 利用享元模式共享一个state对象

     

    优缺点

    优点

    封装了转化规则,对于大量分支语句,可以考虑使用状态类进一步封装。 每个状态都是确定的,所以对象行为是可控的

    缺点

    状态模式的关键是将事物的状态都封装成单独的类,这个类的各种方法就是“此种状态对应的表现行为”, 因此状态类会增加程序开销

     

    总结

    状态模式的使用场景也特别明确,有如下两点

    1. 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为

    2. 一个操作中含有大量的分支语句,而且这些分支语句依赖于该对象的状态。状态通常为一个或多个枚举常量的表示

    简而言之,当遇到很多同级 if-else或者 switch的时候,可以使用状态模式来进行简化

     

  • 相关阅读:
    jQuery的平滑页面内锚定链接插件:$.smoothAnchor()
    分享10个超酷的jQuery动画教程
    jQuery技术在线小测试
    分享一个jQuery的小测验(Quiz)插件:jQuizzy
    (SqlServer)不公开存储过程sp_Msforeachtable与sp_Msforeachdb详解
    SQL Server实用操作小技巧集合
    如何加密和解密文件
    winform程序最小化到托盘后没法关机的解决方案
    SQL语句操作大全
    自定义事件
  • 原文地址:https://www.cnblogs.com/zhazhanitian/p/13573643.html
Copyright © 2011-2022 走看看