V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
march1993
V2EX  ›  JavaScript

GUI 编程有用有限状态机代替 OOP 的吗?

  •  
  •   march1993 · 2016-03-11 12:24:45 +08:00 · 5115 次点击
    这是一个创建于 3203 天前的主题,其中的信息可能已经有所发展或是发生改变。

    写 GUI 的时候为了维护界面的状态一直用 OOP ,但是开发的很慢,也容易出 Bug ,然后就用状态机来实现,感觉还不错,有这么用的小伙伴吗?

    const FSM = function () {
        this.states = [];
        this.current = undefined;
        this.enabled = true;
    };
    FSM.prototype.add = function (name, enter, leave, ...event_foo_pairs) {
        let state = {
            __name__: name,
            enter: enter,
            leave: leave
        };
        event_foo_pairs.forEach(pairs => state[pairs[0]] = pairs[1]);
        this.states.push(state);
        this.states.length === 1 && this.go(name);
    };
    FSM.prototype.go = function (name, ...var_args) {
        const prev = this.states.filter(i => i.__name__ === this.current)
        const can_leave = prev.map(i => i.leave()).reduce((p, n) => p && n, true);
        if (can_leave) {
            const next = this.states.filter(i => i.__name__ === name);
            next.length === 0 && console.error('No such next jump: ', name);
            this.current = name;
            const ret = next.map(i => i.enter.apply(this, var_args)).reduce((p, n) => p && n, true);
            return ret;
        } else {
            console.warn('Can\'t leave state: ', this.current);
            console.warn(new Error().stack);
            return false;
        }
    };
    FSM.prototype.fire = function (event, ...var_args) {
        return this.states.filter(i => i.__name__ === this.current && i.hasOwnProperty(event)).map(s => s[event]).map(i => i.apply(this, var_args));
    };
    
    22 条回复    2016-03-14 16:58:03 +08:00
    shunia
        1
    shunia  
       2016-03-11 12:36:38 +08:00
    把这个问题说的学渣能明白一点,其实就是一个 State 控件(可以支持视图,也可以虚拟的),根据提供的状态进行跳转.
    是这个意思吗?
    yksoft1
        2
    yksoft1  
       2016-03-11 12:44:10 +08:00
    Windows 的消息循环里面一般不就是一个有限状态机么
    twl007
        3
    twl007  
       2016-03-11 12:49:21 +08:00
    OOP 只是编程范式吧 - - 状态机是数学模型吧? 用 OOP 也能实现状态机啊 - - ||||
    mko0okmko0
        4
    mko0okmko0  
       2016-03-11 13:48:22 +08:00
    状态机不是基本吗 XD
    好吧其实是一个门槛,恭喜你迈过去
    murmur
        5
    murmur  
       2016-03-11 14:02:23 +08:00
    最基本的状态机不就是正则表达式么。。另外维护状态什么,好像新的 redux 就是搞这个的
    jiongxiaobu
        6
    jiongxiaobu  
       2016-03-11 14:55:58 +08:00
    react ?
    bdbai
        7
    bdbai  
       2016-03-11 18:29:20 +08:00 via iPhone
    给楼主的思想点个赞。推荐 React 和 Redux 。
    glogo
        8
    glogo  
       2016-03-11 19:33:22 +08:00
    这个思路不错!不过其实维护对象的状态是不是就是在状态机里转哪.....
    quix
        9
    quix  
       2016-03-11 20:26:19 +08:00
    当年的 flex 不就是支持 state 么。 但有时候有多种状态, 一大堆 fsm 也不方便
    march1993
        10
    march1993  
    OP
       2016-03-11 23:00:27 +08:00
    @twl007 是能实现 只是构建模型的时候思考方式不一样啊
    march1993
        11
    march1993  
    OP
       2016-03-11 23:00:41 +08:00
    @mko0okmko0 求高级玩法
    march1993
        12
    march1993  
    OP
       2016-03-11 23:01:26 +08:00
    @quix 状态机可以包含子状态,转移的时候连带自状态一并转移
    我试过中这种方法,代码就不贴了
    也挺清楚的
    march1993
        13
    march1993  
    OP
       2016-03-11 23:01:44 +08:00
    @glogo 也要比 if else 清楚啊
    march1993
        14
    march1993  
    OP
       2016-03-11 23:02:27 +08:00
    @twl007 的确。但是构建问题模型的时候,我指的是这两者的思路
    march1993
        15
    march1993  
    OP
       2016-03-11 23:02:45 +08:00
    @yksoft1 母鸡 很久不研究 windows 的消息系统了
    march1993
        16
    march1993  
    OP
       2016-03-11 23:02:56 +08:00
    @shunia
    mrsatangel
        17
    mrsatangel  
       2016-03-11 23:13:14 +08:00
    想当年在单片机上就有 qpc 状态机+emwin GUI 。用状态机表示目录层级没问题,框架一大复杂度急剧增加,维护状态机本身的开销比较大。另外呢 FSM 本身不足以作为一种 paradigm 和 OOP 比较
    mko0okmko0
        18
    mko0okmko0  
       2016-03-12 01:01:30 +08:00
    @march1993
    我没办法教,我是写五年累积经验.
    持续学习和累积经验是唯一解.
    noli
        19
    noli  
       2016-03-12 01:21:01 +08:00
    JS 不是 GUI 的好工具。模拟 OOP 本身就挺费力的。

    看看 OC 或者 C# 你才可以感受到为什么 OOP 在 GUI 领域是特别好的工具。
    zhuangzhuang1988
        20
    zhuangzhuang1988  
       2016-03-12 19:52:50 +08:00
    状态机? 可以看这个。。。 https://book.douban.com/subject/6886605/ 在最后有关于状态机 UI 编程。。
    代码大概这样

    let rec drawingLoop(clr, from) = async {
    let! move = Async.AwaitEvent(form.MouseMove) #1
    if (move.Button &&& MouseButtons.Left) = MouseButtons.Left then
    drawRectangle(clr, from, (move.X, move.Y)) #2
    return! drawingLoop(clr, from) #2
    else
    return (move.X, move.Y)
    } #3

    let waitingLoop() = async {
    while true do #4
    let! down = Async.AwaitEvent(form.MouseDown)
    let downPos = (down.X, down.Y)
    if (down.Button &&& MouseButtons.Left) = MouseButtons.Left then
    let! upPos = drawingLoop(Color.IndianRed, downPos) #5
    do printfn "Drawn rectanlge (%A, %A)" downPos upPos
    }

    #A Wait for the next mouse action
    #2 Refresh rectangle and continue in the 'Drawing' state
    #3 Return end location to the 'Waiting' state
    #4 Repeat after drawing finishes
    #5 Transition to the 'Drawing' state
    march1993
        21
    march1993  
    OP
       2016-03-14 16:52:00 +08:00
    @noli OC, swift, C# 数据绑定是好用啊,但也没有那么好用啊
    march1993
        22
    march1993  
    OP
       2016-03-14 16:58:03 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1096 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 23:02 · PVG 07:02 · LAX 15:02 · JFK 18:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.