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

2016-03-11 12:24:45 +08:00
 march1993

写 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));
};
5096 次点击
所在节点    JavaScript
22 条回复
shunia
2016-03-11 12:36:38 +08:00
把这个问题说的学渣能明白一点,其实就是一个 State 控件(可以支持视图,也可以虚拟的),根据提供的状态进行跳转.
是这个意思吗?
yksoft1
2016-03-11 12:44:10 +08:00
Windows 的消息循环里面一般不就是一个有限状态机么
twl007
2016-03-11 12:49:21 +08:00
OOP 只是编程范式吧 - - 状态机是数学模型吧? 用 OOP 也能实现状态机啊 - - ||||
mko0okmko0
2016-03-11 13:48:22 +08:00
状态机不是基本吗 XD
好吧其实是一个门槛,恭喜你迈过去
murmur
2016-03-11 14:02:23 +08:00
最基本的状态机不就是正则表达式么。。另外维护状态什么,好像新的 redux 就是搞这个的
jiongxiaobu
2016-03-11 14:55:58 +08:00
react ?
bdbai
2016-03-11 18:29:20 +08:00
给楼主的思想点个赞。推荐 React 和 Redux 。
glogo
2016-03-11 19:33:22 +08:00
这个思路不错!不过其实维护对象的状态是不是就是在状态机里转哪.....
quix
2016-03-11 20:26:19 +08:00
当年的 flex 不就是支持 state 么。 但有时候有多种状态, 一大堆 fsm 也不方便
march1993
2016-03-11 23:00:27 +08:00
@twl007 是能实现 只是构建模型的时候思考方式不一样啊
march1993
2016-03-11 23:00:41 +08:00
@mko0okmko0 求高级玩法
march1993
2016-03-11 23:01:26 +08:00
@quix 状态机可以包含子状态,转移的时候连带自状态一并转移
我试过中这种方法,代码就不贴了
也挺清楚的
march1993
2016-03-11 23:01:44 +08:00
@glogo 也要比 if else 清楚啊
march1993
2016-03-11 23:02:27 +08:00
@twl007 的确。但是构建问题模型的时候,我指的是这两者的思路
march1993
2016-03-11 23:02:45 +08:00
@yksoft1 母鸡 很久不研究 windows 的消息系统了
march1993
2016-03-11 23:02:56 +08:00
@shunia
mrsatangel
2016-03-11 23:13:14 +08:00
想当年在单片机上就有 qpc 状态机+emwin GUI 。用状态机表示目录层级没问题,框架一大复杂度急剧增加,维护状态机本身的开销比较大。另外呢 FSM 本身不足以作为一种 paradigm 和 OOP 比较
mko0okmko0
2016-03-12 01:01:30 +08:00
@march1993
我没办法教,我是写五年累积经验.
持续学习和累积经验是唯一解.
noli
2016-03-12 01:21:01 +08:00
JS 不是 GUI 的好工具。模拟 OOP 本身就挺费力的。

看看 OC 或者 C# 你才可以感受到为什么 OOP 在 GUI 领域是特别好的工具。
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

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/262752

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX