April 23, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Working With Design Patterns: State

  • June 19, 2008
  • By Jeff Langr
  • Send Email »
  • More Articles »

Conditional logic is essential to building any application, yet too much can make an application incomprehensible. Many of the applications I build require that an object exist in many different states, with behavior differing from state to state. A straightforward implementation involves lots of if statements and complex conditionals, producing overly convoluted solutions in short order. As a remedy, I use the state design pattern to keep my code from getting out of hand.

Holdings in a library provide a good example. A holding is a copy of a book (see Listing 1). (In my implementation, the book is simply the ISBN classification information. Thus, each holding object references a copy number and a book object.) Holdings can be checked out, checked in, they can be moved from branch to branch, they can be held by a patron, they can be warehoused, and so on. Each of these events puts the holding into a state where different rules apply. For example, a book that's checked out obviously can't be warehoused.

Listing 1: The Book class.

// 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;
   }
}

Listing 2 shows a starter implementation for Holding. (Note that I'm not yet concerned with the relevancy of the patron ID.)

Listing 2: An initial Holding implementation.

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;
   }
}




Page 1 of 4



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel