#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('Турникет разблокирован, и посетитель может пройти.'); } }
Комментариев нет:
Отправить комментарий