SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

デザインパターンの使い方

デザインパターンの使い方: Command

Commandパターンを利用したソースコードのリファクタリング

 次に、LibrarySystemTestの名前をAddPatronCommandTestに変更し、AddPatronCommandを直接呼び出すように書き換えます。変更後のテストをリスト4に示します。変更箇所は太字で示しています。

リスト4 AddPatronCommandTest
public class ''AddPatronCommandTest'' {
   @Test
   public void ''execute''() {
      final List<Patron> added = new ArrayList<Patron>();
      LibrarySystem system = new LibrarySystem() {
         @Override
         public void add(Patron patron) {
            added.add(patron);
         }
      };

      Request request = new Request();
      request.setParameter("command", "addPatron");
      request.setParameter("name", "patronName");
      request.setParameter("id", "patronId");

      ''AddPatronCommand command = new AddPatronCommand(request, system);''
      ''command.execute();''

      assertEquals(1, added.size());
      assertEquals("patronName", added.get(0).getName());
      assertEquals("patronId", added.get(0).getId());
   }
}

 LibrarySystemTestクラスの名前を変更したので、LibrarySystemをテストすることができなくなりました。この問題はすぐ後で再度取り上げます。先に、LibrarySystemとAddPatronCommandの密結合を取り除くことにします。これにはメソッドとフィールドを正しく移動させる必要があります。add(Patron)メソッドを移動しなければならないことは間違いありません。add(Patron)メソッドを移動した後に、コンパイラを使用して他にどのメソッドやフィールドを移動させる必要があるかを調べたところ、add(Patron)に関してはデータアクセスフィールドもコピーする必要があるとわかりました。

 変更後のテストとAddPatronCommandクラスは下記のとおりですが、内容はあまり変わっていません(リスト5と6を参照)。

リスト5 変更後のAddPatronCommandTest
public class AddPatronCommandTest {
   @Test
   public void execute() {
      Request request = new Request();
      request.setParameter("command", "addPatron");
      request.setParameter("name", "patronName");
      request.setParameter("id", "patronId");

      final List<Patron> added = new ArrayList<Patron>();

      AddPatronCommand command = new AddPatronCommand(request) {
         @Override
         public void add(Patron patron) {
            added.add(patron);
         }
      };

      command.execute();

      assertEquals(1, added.size());
      assertEquals("patronName", added.get(0).getName());
      assertEquals("patronId", added.get(0).getId());
   }
}
テスト6 変更後のAddPatronCommand
public class AddPatronCommand implements Command {
   private String name;
   private String id;
   ...

   public AddPatronCommand(Request request) {
      name = request.getParameter("name");
      id = request.getParameter("id");
   }

   public void execute() {
      Patron patron = new Patron(name, id);
      add(patron);
   }

   public void add(Patron patron) {
      ...
   }
}

 このリファクタリングパターンを使用して、このようなコマンドクラスを段階的に作成していくことができます。2つ目のコマンドクラスに取り組んでいるときに、両方のコマンドが同じメソッド(execute)をサポートしていることに気が付いたので、Commandインターフェイスを作成し(リスト7を参照)、各コマンドクラスがこのインターフェイスを実装するように変更しました。

リスト7 Commandインターフェイス
public interface Command {
   void execute();
}

次のページ

この記事は参考になりましたか?

デザインパターンの使い方連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Jeff Langr(Jeff Langr)

本格的なソフトウェアの開発に四半世紀以上携わってきたベテランのソフトウェア開発者。『Agile Java: Crafting Code With Test-Driven Development』(Prentice Hall、2005年)と、他の1冊の著書がある。『Clean Code』(Uncle Bob Martin著、Prentice Hall、2008年8月)にも寄稿している。また、ソフトウェア開発に関する記事を80件以上執筆しており、そのうちの...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/2974 2008/09/12 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー