• 设计模式-状态模式


    介绍

    • 一个对象有状态变化
    • 每次状态变化都会触发一个逻辑
    • 不能总是用if else来控制

    示例

    • 交通信号灯不同颜色的变化

    UML类图

    • 传统UML类图
      传统UML类图

    • 简化后的UML类图
      简化后的UML类图

    代码演示

    // 状态(红灯、绿灯、黄灯)
    class State {
        constructor(color) {
            this.color = color;
        }
        // 设置状态
        handle(context) {
            console.log(`turn to ${this.color} light`)
            context.setState(this)
        }
    }
    
    // 主体
    class Context {
        consructor() {
            this.state = null
        }
        // 获取状态
        getState() {
            return this.state
        }
        setState(state) {
            this.state = state
        }
    }
    
    // test
    let context = new Context()
    
    let green = new State('green')
    let yellow = new State('yellow')
    let red = new State('red')
    
    // 绿灯亮了
    green.handle(context)
    console.log(context.getState())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    场景

    有限状态机

    • 有限个状态、以及在这些状态之间的变化
    • 如交通信号灯
    • 使用开源lib:javascript-state-machine
    • github.com/jakesgordon/javascript-state-machine

    有限状态机- “收藏”和“取消”

    // 状态机模型
    var fsm = new StateMachine({
        init: '收藏', // 初始状态,待收藏
        transitions: [
            {
                name: 'doStore',
                from: '收藏',
                to: '取消收藏'
            },
            {
                name: 'deleteStore',
                from: '取消收藏',
                to: '收藏'
            }
        ],
        methods: {
            // 执行收藏
            onDoStore: function () {
                alert('收藏成功')
                updateText()
            },
            // 取消收藏
            onDeleteStore: function () {
                alert('已取消收藏')
                updateText()
            }
        }
    })
    
    var $btn = $('#btn')
    
    // 点击事件
    $btn.click(function() {
        if (fsm.is('收藏')) {
            fsm.doStore()
        } else {
            fsm.deleteStore()
        }
    })
    
    // 更新文案
    function updateText() {
        $btn.text(fsm.state)
    }
    
    // 初始化文案
    updateText()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    写一个简单的Promise

    • 回顾Promise的语法
    function loadImg(src) {
        const promise = new Promise(function (resolve, reject) {
            var img = document.createElement('img');
            img.onload = function() {
                resolve(img)
            }
            img.onerror = function() {
                reject()
            }
            img.src = src
        })
        return promise
    }
    
    var src = '';
    var result = loadImg(src)
    
    result.then(function(img){
        console.log('success 1')
    }, function() {
        console.log('failed 1')
    })
    result.then(function(img) {
        console.log('success 2')
    }, function() {
        console.log('failed 2')
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 分析:Promise就是一个有限状态机

      • Promise三种状态:pending fullfilled rejected
      • pending -> fullfilled或者 pending -> rejected
      • 不能逆向变化
    • 写代码

    // 模型
    var fsm = new StateMachine({
        init: 'pending',
        transitions: [
            {
                name: 'resolve',
                from: 'pending',
                to: 'fullfilled'
            },
            {
                name: 'reject',
                from: 'pending',
                to: 'rejected'
            }
        ],
        methods: {
            // 成功
            onResolve: function (state, data) {
                // 参数:state - 当前状态实例;data - fsm.resolve(xxx) 执行时传递过来的参数
                data.successList.forEach(fn => fn())
            },
            // 失败
            onReject: function (state, data) {
                // 参数: state - 当前状态实例;data - fsm.reject(xxx)   执行时传递过来的参数
                data.failList.forEach(fn => fn())
            }
        }
    })
    
    // 定义Promise
    class MyPromise {
        // fn 回调函数
        constructor(fn) {
            this.successList = []
            this.failList = []
            
            // 接收两个函数参数,第一个为resolve回调,第二个为reject回调
            fn(() => {
                // resolve 函数 
                fsm.resolve(this) // fsm触发onResolve函数
            }, () => {
                // reject 函数
                fsm.reject(this) // fsm触发onResolve函数
            })
        }
        // then函数,successFn failFn 不会立即执行,放进数组里
        then(successFn, failFn) {
            this.successList.push(successFn)
            this.failList.push(failFn)
        }
    }
    
    // 测试代码
    function loadImg(src) {
        const promise = new MyPromise(function (resolve, reject) {
            let img = document.createElement('img')
            img.onload = function() {
                resolve(img)
            }
            img.onerror = function() {
                reject()
            }
            img.src = src
        })
        return promise
    }
    
    let src = 'https://imgxxx';
    let result = loadImg(src)
    
    result.then(function() {
        console.log('ok1')
    }, function() {
        console.log('fail1')
    })
    
    result.then(function() {
        console.log('ok2')
    }, function() {
        console.log('fail2')
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    设计原则验证

    • 将状态对象和主题对象分离,状态的变化逻辑单独处理
    • 符合开放封闭原则
  • 相关阅读:
    ⑮霍兰德EA*型如何选专业?高考志愿填报选专业
    Design A NearBy Friends
    kafka
    2309C++测试miniz简单压缩
    【SA8295P 源码分析】127 - 摄像头 GMSL1、GMSL2 加串-解串器 常用寄存器配置整理(正在更新中......)
    设计思维|如何构建价值导向的设计思维?
    05【数组的扩展】
    【高德】改变地图的背景色为自定义样式
    【组合递归】【StringBuilder】Leetcode 17. 电话号码的字母组合
    c++模板初阶
  • 原文地址:https://blog.csdn.net/linanran1027/article/details/133636790