Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

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

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2008/12/12 14:00

 アプリケーションを作成する上で条件ロジックを欠くことはできません。しかし、あまりに多用すると入り組んできて分かりにくくなります。このような事態をできるだけ避けるために、私はStateデザインパターンを使ってコードをすっきりさせています。本稿では、Stateデザインパターンの利用方法を例を示しながら説明します。

目次

Stateパターンの例

 アプリケーションを作成する上で条件ロジックを欠くことはできません。しかし、あまりに多用すると入り組んできて分かりにくくなります。私が作成する多くのアプリケーションでは、オブジェクトはさまざまな状態で存在し、状態ごとにそれぞれ異なる動作をします。if文と複雑な条件分岐を多用する「直球型」の実装では、すぐに複雑怪奇なソリューションになってしまいます。このような事態をできるだけ避けるために、私はStateデザインパターンを使ってコードをすっきりさせています。

 図書館の取り置き本を例に説明しましょう。取り置き本(Holding)オブジェクトは、本(Book)オブジェクト(リスト1を参照)のコピーです(今回の実装では、BookはISBNの分類情報にすぎません。従って、各Holdingオブジェクトはコピー番号とBookオブジェクトを参照します)。Holdingオブジェクトの状態として、貸し出しと返却があります。図書館と図書館の間での移動もあります。利用者に所持されたり、保管庫に入れられたりもします。これらの各イベントによって、Holdingオブジェクトはさまざまな規則が適用される状態に遷移します。例えば、「貸し出し中」状態の本を保管庫で保管することはできません。

リスト1 Bookクラス
// BookTest.java
import static org.junit.Assert.*;
import org.junit.*;

public class BookTest {
   public static final Book CATCH22 = new Book("0-671-12805-1",
      "Catch-22", "Heller, Joseph", "1961");

   @Test
   public void create() {
      assertEquals("0-671-12805-1", CATCH22.getIsbn());
      assertEquals("Catch-22", CATCH22.getTitle());
      assertEquals("Heller, Joseph", CATCH22.getAuthor());
      assertEquals("1961", CATCH22.getYear());
   }
}

// Book.java
public class Book {
   private final String isbn;
   private final String title;
   private final String author;
   private final String year;

   public Book(String isbn, String title, String author,
      String year) {
      this.isbn = isbn;
      this.title = title;
      this.author = author;
      this.year = year;
   }

   public String getIsbn() {
      return isbn;
   }

   public String getTitle() {
      return title;
   }

   public String getAuthor() {
      return author;
   }

   public String getYear() {
      return year;
   }
}

 リスト2に、Holdingの最初の実装を示します(利用者IDとの関連はまだ考慮していません)。

リスト2 Holdingの最初の実装
import static org.junit.Assert.*;
import java.util.Date;
import org.junit.*;

public class HoldingTest {
   private Holding holding;
   private static final Date NOW = new Date();
   private static final String PATRON_ID = "12345";

   @Before
   public void initialize() {
      Book book = BookTest.CATCH22;
      int copyNumber = 1;
      holding = new Holding(book, copyNumber);
   }

   @Test
   public void create() {
      assertSame(BookTest.CATCH22, holding.getBook());
      assertEquals(1, holding.getCopyNumber());
      assertFalse(holding.isOnLoan());
   }

   @Test
   public void checkout() {
      holding.checkout(NOW, PATRON_ID);
      assertTrue(holding.isOnLoan());
      assertEquals(NOW, holding.getLoanDate());
   }

   @Test
   public void checkin() {
      Date later = new Date(NOW.getTime() + 1);
      holding.checkout(NOW, PATRON_ID);
      holding.checkin(later);
      assertFalse(holding.isOnLoan());
   }
}

// Holding.java
import java.util.Date;

public class Holding {
   private final Book book;
   private final int copyNumber;
   private Date checkoutDate;

   public Holding(Book book, int copyNumber) {
      this.book = book;
      this.copyNumber = copyNumber;
   }

   public Book getBook() {
      return book;
   }

   public int getCopyNumber() {
      return copyNumber;
   }

   public boolean isOnLoan() {
      return checkoutDate != null;
   }

   public Date getLoanDate() {
      return checkoutDate;
   }

   public void checkout(Date date, String patronId) {
      checkoutDate = date;
   }

   public void checkin(Date date) {
      checkoutDate = null;
   }
}

  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

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

    japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.com や EarthWeb.c...

  • Jeff Langr(Jeff Langr)

    本格的なソフトウェアの開発に四半世紀以上携わってきたベテランのソフトウェア開発者。『Agile Java: Crafting Code With Test-Driven Development』(Prentice Hall、2005年)と、他の1冊の著書がある。『Clean Code』(Uncle...

バックナンバー

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

もっと読む

All contents copyright © 2005-2018 Shoeisha Co., Ltd. All rights reserved. ver.1.5