设计模式-状态模式

介绍

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

示例

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

UML类图

  • 传统UML类图

  • 简化后的UML类图

代码演示

js 复制代码
// 状态(红灯、绿灯、黄灯)
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())

场景

有限状态机

有限状态机- "收藏"和"取消"

js 复制代码
// 状态机模型
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()

写一个简单的Promise

  • 回顾Promise的语法
js 复制代码
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')
})
  • 分析:Promise就是一个有限状态机

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

js 复制代码
// 模型
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')
})

设计原则验证

  • 将状态对象和主题对象分离,状态的变化逻辑单独处理
  • 符合开放封闭原则
相关推荐
岳轩子5 分钟前
23种设计模式之原型模式
设计模式·原型模式
十五年专注C++开发29 分钟前
C++中的链式操作原理与应用(一)
开发语言·c++·设计模式
多多*1 小时前
后端并发编程操作简述 Java高并发程序设计 六类并发容器 七种线程池 四种阻塞队列
java·开发语言·前端·数据结构·算法·状态模式
旺代3 小时前
C++设计模式(单例模式)
c++·单例模式·设计模式
LightOfNight3 小时前
【设计模式】创建型模式之单例模式(饿汉式 懒汉式 Golang实现)
单例模式·设计模式·golang
那年星空12 小时前
Flutter 设计模式全面解析:抽象工厂
flutter·设计模式·架构
博风13 小时前
设计模式:10、外观模式
设计模式·外观模式
你好helloworld15 小时前
设计模式之观察者模式
观察者模式·设计模式
zzzhpzhpzzz19 小时前
设计模式——抽象工厂模式
设计模式·抽象工厂模式
阳光开朗_大男孩儿20 小时前
组合设计模式
c++·设计模式·组合模式·组合设计模式