#javascript #инспекция_кода
Набросал пример исходя из описания алгоритма. Хочу услышать замечания, что стоило бы изменить в этом коде: // https://en.wikipedia.org/wiki/Finite-state_machine // https://en.wikipedia.org/wiki/Event-driven_finite-state_machine class FSM { constructor(transitions = []) { this.transitions = new Map(); for (let { from, event, to, action } of transitions) { this.addTransition(from, event, to, action); } this.currentState = transitions.length ? transitions[0].from : null; } addTransition(from, event, to, action) { let events = this.transitions.get(from); if (!events) { events = new Map(); this.transitions.set(from, events); } events.set(event, { to, action }); } emit(event, ...args) { const events = this.transitions.get(this.currentState); if (events) { const obj = events.get(event); if (obj) { this.currentState = obj.to; obj.action.apply(this, args); } } } } const turnstile = new FSM([{ from: 'locked', event: 'coin', to: 'unlocked', action: () => { console.log('Турникет разблокирован, и посетитель может пройти.'); } }, { from: 'locked', event: 'push', to: 'locked', action: () => { console.log('Посетитель толкает турникет, но тот заблокирован.'); } }, { from: 'unlocked', event: 'coin', to: 'unlocked', action: () => { console.log('Посетитель опускает еще одну монету в турникет, состояние не меняется.'); } }, { from: 'unlocked', event: 'push', to: 'locked', action: () => { console.log('Как только посетитель проходит, турникет блокируется.'); } }, ]); turnstile.emit('push'); turnstile.emit('coin'); turnstile.emit('coin'); turnstile.emit('push'); turnstile.emit('push'); Вывод: Посетитель толкает турникет, но тот заблокирован. Турникет разблокирован, и посетитель может пройти. Посетитель опускает еще одну монету в турникет, состояние не меняется. Как только посетитель проходит, турникет блокируется. Посетитель толкает турникет, но тот заблокирован.
Ответы
Ответ 1
просто ещё один способ: class Au { constructor(States, Symbols, Table, currentState = States[Object.keys(States)[0]]) { this.States = States; this.Symbols = Symbols; this.Table = Table; this.currentState = currentState; ch(States, Symbols); info(States, Symbols, Table); } emit(_Symbol, ..._args) { let qqw = this.Table[this.currentState + _Symbol]; let state = null; if (qqw) { if (qqw[0]) this.currentState = qqw[0]; if (qqw[1]) qqw[1].apply(null, _args); } } } const turnstile = (function() { const States = { locked: 1 << 0, unlocked: 1 << 1, }; const Symbols = { coin: 1 << 2, push: 1 << 3, }; const Table = { [States.locked + Symbols.coin]: [States.unlocked, () => console.log('Турникет разблокирован, и посетитель может пройти.')], [States.locked + Symbols.push]: [States.locked, () => console.log('Посетитель толкает турникет, но тот заблокирован.')], [States.unlocked + Symbols.coin]: [States.unlocked, () => console.log('Посетитель опускает еще одну монету в турникет, состояние не меняется.')], [States.unlocked + Symbols.push]: [States.locked, () => console.log('Как только посетитель проходит, турникет блокируется.')], }; return new Au(States, Symbols, Table); })(); turnstile.emit(turnstile.Symbols.push); turnstile.emit(turnstile.Symbols.coin); turnstile.emit(turnstile.Symbols.coin); turnstile.emit(turnstile.Symbols.push); turnstile.emit(turnstile.Symbols.push); // -- function ch(States, Symbols) { let a = Object.keys(States); let b = Object.keys(Symbols); let ch = new Set([...a, ...b]); if (ch.size !== (a.length + b.length)) { throw new Error('номера ключей States и Symbols совпадают'); } } function info(States, Symbols, Table) { let l = { 'количество возможных комбинаций': Object.keys(States).length * Object.keys(Symbols).length, 'текущее количество комбинаций': Object.keys(Table).length, }; Object.keys(l).forEach(_k => console.log(_k, l[_k])); } наверное, this не нужен obj.action.apply(this, args); считаю что повторяющийся код, во избежании ошибок, должен быть в функции или классе { from: 'locked', event: 'coin', to: 'unlocked', action: () => { console.log('Турникет разблокирован, и посетитель может пройти.'); } }
Комментариев нет:
Отправить комментарий