連続する一連の処理を行う方法は、コマンドのキューイングを使うことで落ち着いているが、処理中のキューを中断するインタフェースを設計していなかった。つまり、一度引き金を引いたら弾を撃ち尽くすまで止められない、という状況だった。
なので、早急にコマンドとインボーカに abort を実装し、いかなる状態でも処理を中断できるようにした。クライアントオブジェクトは、インボーカの abort を呼び出せば、実行しているコマンドを意識することなく処理を中断 (正しくは破棄) できる。
例えば、ある段階で処理する内容が、
- XML の読み込み
- Tween アニメーション
というオーダの場合、各々のプロセスをコマンドに置き換えると以下のようになる。
loadXMLCommand
class loadXMLCommand extends AbstractCommand {
//実行の実装
public function execute():Void {...};
//完了の実装
public function done():Void {...};
}
playTweenAnimationCommand
class playTweenAnimationCommand extends AbstractCommand {
//実行と完了の実装
}
そして、これらに中断時の処理を実装する。XML ロードコマンドならばローダの破棄、Tween アニメーションのコマンドならば、Tween を停止し、リスナの解除等を行えばよいだろう。
class playTweenAnimationACommand extends AbstractCommand {
//破棄の実装
public function abort():Void {
this.tween.stop();
this.tween.removeListener(this.tweenListner);
}
}
次に、インボーカ側の abort の実装例。現在処理中のコマンドと、待ち行列に入っているコマンドの abort を呼び出す。
class Invoker {
public function abort():Void {
this.aborted = true;
//現在処理中のコマンドを破棄する
this.currentCommand.abort();
//キューに残っているコマンドを破棄する
while (this.commandQueue.getLength() > 0) {
var command:AbstractCommand = this.commandQueue.dequeue();
command.abort();
}
}
}
デストラクタの定義と同様に、プロセスの管理方法を徹底しておけば、後々になって苦労しなくて済むだろう。