CompensableCommand インターフェースは、アプリケーション・プログラマーが実装しなければならない getCompensatingCommand メソッドを宣言します。
以下のコード例は、ModifyCheckingAccountCmd コマンドのための実装を表示しています。 実装は単に、現行のコマンドと関連した ModifyCheckingAccountCompensatorCmd コマンドのインスタンスを戻します。
public class ModifyCheckingAccountCmdImpl extends TargetableCommandImpl implements ModifyCheckingAccountCmd { ... // Method from CompensableCommand interface public Command getCompensatingCommand() throws CommandException { modifyCheckingAccountCompensatorCmd = new ModifyCheckingAccountCompensatorCmd(this); return (Command)modifyCheckingAccountCompensatorCmd; } }
補正可能なコマンドを使用するアプリケーションは、2 つの別 々なコマンドである、(CompensableCommand として宣言された) 基本コマンドと補正コマンドを必要とします。 サンプルのアプリケーションでは、基本コマンドは ModifyCheckingAccountCmd インターフェース内で宣言され、ModifyCheckingAccountCmdImpl クラス内に実装されます。 このコマンドも補正可能なコマンドなので、これに関連し、この処理を元に戻すために設計された第 2 のコマンドがあります。 補正可能コマンドを作成する場合は、補正コマンドも書き込む必要があります。
... public class ModifyCheckingAccountCompensatorCmd extends TargetableCommandImpl { public ModifyCheckingAccountCmdImpl modifyCheckingAccountCmdImpl; public CheckingAccount checkingAccount; public ModifyCheckingAccountCompensatorCmd( ModifyCheckingAccountCmdImpl originalCmd) { // Get an instance of the original command modifyCheckingAccountCmdImpl = originalCmd; // Get the relevant account checkingAccount = originalCmd.getCheckingAccount(); } // Methods from the Command and Targetable Command interfaces .... }
performExecute メソッドは、実際の当座預金残高が、元のコマンドが戻したものと一致することを検証します。 一致している場合は、ModifyCheckingAccountCmd コマンドを使用して、現 行の残高を前に保管されていた残高と置き換えます。 最後に、補正コマンドを元に戻すことが必要となる場合に備え、最新の 残高が保管されます。 リセット・メソッドには行うべき作業はありません。
... public class ModifyCheckingAccountCompensatorCmd extends TargetableCommandImpl { // Variables and constructor .... // Methods from the Command and TargetableCommand interfaces public boolean isReadyToCallExecute() { if (checkingAccount != null) return true; else return false; } public void performExecute() throws CommandException { try { ModifyCheckingAccountCmdImpl originalCmd = modifyCheckingAccountCmdImpl; // Retrieve the checking account modified by the original command CheckingAccount checkingAccount = originalCmd.getCheckingAccount(); if (modifyCheckingAccountCmdImpl.balance == checkingAccount.getBalance()) { // Reset the values on the original command checkingAccount.setBalance(originalCmd.oldBalance); float temp = modifyCheckingAccountCmdImpl.balance; originalCmd.balance = originalCmd.oldBalance; originalCmd.oldBalance = temp; } else { // Balances are inconsistent, so we cannot compensate throw new CommandException( "Object modified since this command ran."); } } catch (Exception e) { System.out.println(e.getMessage()); } } public void reset() {} }