これで、Commandオブジェクトを返すだけのファクトリクラスを作成することができます(リスト8を参照)。
public class CommandFactory { public static Command create(Request request) { String command = request.getParameter("command"); if (command == null) return null; if (command.equals("return")) return new ReturnCommand(request); if (command.equals("addPatron")) return new AddPatronCommand(request); return null; } }
CommandFactoryのテストは簡単に作成できます(リスト9)。
public class CommandFactoryTest { private Request request; @Before public void initialize() { request = new Request(); } @Test public void createValidCommands() { assertCommandType("return", ReturnCommand.class); assertCommandType("addPatron", AddPatronCommand.class); } @Test public void createWithNoCommandParameter() { assertNull(CommandFactory.create(request)); } @Test public void createWithBadCommandParameter() { request.setParameter("command", "badCommand"); assertNull(CommandFactory.create(request)); } private void assertCommandType(String commandArgument, Class commandClass) { request.setParameter("command", commandArgument); assertEquals(commandClass, CommandFactory.create(request).getClass()); } }
ここまで来れば、serviceメソッドのコードを、このCommandFactoryを利用するように変更できます(リスト10を参照)。
public void service(Request request) { String command = request.getParameter("command"); if (command.equals("checkout")) { ... } else if (command.equals("newBranch")) { ... } else if (command.equals("addBook")) { ... } else { libraryCommand = CommandFactory.create(request); libraryCommand.execute(); } }
最終的には、serviceメソッド内のすべてのコードがCommandFactoryを使用するようにリファクタリングできます。serviceメソッド内のすべてのブロックをこのコマンドフレームワークに移動すると、以下のようになります。
public void service(Request request) { Command command = CommandFactory.create(request); command.execute(); }
かなりすっきりしましたね。この時点の単体テストでは、serviceメソッドがこのファクトリを使用してコマンドを実行していることを確認できるよう、十分なテストカバレッジを実現する必要があります。各コマンドクラスを再テストする必要はありません。必要なのは、作成されたコマンドに対してexecuteメソッドが呼び出されているか確認することだけです。
