Просили тут онлайн и оффлайн дать пример в статью про состояния. Хорошо, возьмем вот этот эффект. Пример всего с четырьмя состояниями и без особо чего-то сложного, но все же.
Полностью исходный код можно скачать тут.
Итак, у нас есть 4 состояния:
private const INVISIBLE: String = "invisible";
private const SHOW: String = "show";
private const VISIBLE: String = "visible";
private const HIDE: String = "hide";
Конфигурация state machine проводится вот так вот:
state = new StateMachine();
state.add( INVISIBLE, VISIBLE, SHOW );
state.add( VISIBLE, INVISIBLE, HIDE );
state.addTransitionListener( StateMachine.ANY, INVISIBLE, stateInvisible );
state.addTransitionListener( StateMachine.ANY, HIDE, stateHide );
state.addTransitionListener( StateMachine.ANY, VISIBLE, stateVisible );
state.addTransitionListener( StateMachine.ANY, SHOW, stateShow );
Как видите, добавляем переходы из INVISIBLE в VISIBLE через виртуальное состояние SHOW и из VISIBLE в INVISIBLE через HIDE. Далее, парочку листенеров в 4 состояния.
public function show(): void
{
state.setState( VISIBLE );
}
public function hide(): void
{
state.setState( INVISIBLE );
}
В public API эффекта экспортим две функции, в которых просто меняем состояния. За возможность такого изменения отвечает StateMachine.
Ну и, наконец, добавляем листенеры состояний:
private function stateInvisible(): void
{
_obj.visible = false;
}
private function stateHide(): void
{
...
TweenLite.to( {x:0}, 1.0, {x:1, delay: .1 + .01 * effect.numChildren + .2, onComplete: clean} );
}
private function stateVisible(): void
{
_obj.visible = true;
}
private function stateShow(): void
{
...
TweenLite.to( {x:0}, 1.0, {x:1, delay: .1 + .01 * effect.numChildren + .2, onComplete: clean} );
}
В stateHide и stateShow добавляется пустой твин, который заканчивается после всей анимации (да, нужно было использовать какой-нить setInterval, но не в этом суть) и вызывает метод clean, который в свою очередь выполняет state.release() для продолжения сложного перехода состояний.
private function clean(): void
{
...
state.release();
}
Вот и все. Ссылка на полный код доступна в самом начале поста.
Что мы имеем:
- Понятное и логичное программное разделение на состояния
- Невозможность выполнение непредвиденного кода, если это изначально не предусмотрено в данном состоянии (или если StateMachine не сломается)
- Легкость отладки
Плюсы на лицо, особенно с кучей состояний и сложными переходами. В таком случае код делится на стопку функций вида STATE_FUNC, например invisible_show. И сразу можно отследить, ага, я сейчас в состоянии INVISIBLE, значит за обработку этого события отвечает вооон та функция… поглядимссс.