連続する一連の処理を行う方法は、コマンドのキューイングを使うことで落ち着いているが、処理中のキューを中断するインタフェースを設計していなかった。つまり、一度引き金を引いたら弾を撃ち尽くすまで止められない、という状況だった。
なので、早急にコマンドとインボーカに 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(); } } }
デストラクタの定義と同様に、プロセスの管理方法を徹底しておけば、後々になって苦労しなくて済むだろう。