dcsimg
August 8, 2020
Hot Topics:

Working With Design Patterns: Prototype

  • By Jeff Langr
  • Send Email »
  • More Articles »

The prototype pattern suggests that the catalog tell the prototype object (in this case, the Book object) to return a clone of itself. In other words, the Book class should do all the work. Adding the Movie type, in turn, suggests that the solution should be polymorphic.

A more robust and refactored solution that incorporates the notion of a prototype appears in Listings 4 (the tests) and 5 (the production code). Listing 6 shows the Material, Book, and Movie classes.

Listing 4: Tests to drive out use of prototype.

import static org.junit.Assert.*;

import java.util.*;
import org.junit.*;

public class CatalogTest {
   private Catalog catalog;

   @Before
   public void initialize() {
      catalog = new Catalog();
   }

   @Test
   public void isEmptyOnCreation() {
      assertEquals(0, catalog.size());
   }

   @Test
   public void addNewBook() {
      final Book book = new Book("QA123", "author", "title",
                                 "1999", 1);
      catalog.addNew(book);
      assertEquals(1, catalog.size());
      List<Material> materials = catalog.get("QA123");
      assertEquals(1, materials.size());
      assertSame(book, materials.get(0));
   }

   @Test(expected=NoExistingCopyException.class)
   public void addNewCopyThrowsIfNoExistingCopy() {
      catalog.addCopy("QA123.4");
   }

   @Test
   public void addCopyViaPrototype() {
      final Book book = new Book("QA123", "title", "author",
                                 "1999", 1);
      catalog.addNew(book);
      catalog.addCopy("QA123");

      assertEquals(2, catalog.size());
      assertMaterialCopies("QA123", 2, book);
   }

   @Test
   public void addMovieCopyViaPrototype() {
      final Movie movie = new Movie("DD890", "Shining", "Kubrick",
                                    "2006", 1, Movie.Format.DVD);
      catalog.addNew(movie);
      catalog.addCopy("DD890");

      assertEquals(2, catalog.size());
      assertMovieCopies("DD890", 2, movie);
   }

   private void assertMaterialCopies(String classification,
      int number, Material material) {
      List<Material> materials = catalog.get(classification);
      assertEquals(number, materials.size());

      for (int i = 0; i < number; i++) {
         Material copy = materials.get(i);
         assertEquals(material.getClass(), copy.getClass());
         assertEquals(material.getClassification(),
                      copy.getClassification());
         assertEquals(material.getAuthor(), copy.getAuthor());
         assertEquals(material.getTitle(), copy.getTitle());
         assertEquals(material.getYear(), copy.getYear());
         assertEquals(i + 1, copy.getCopyNumber());
      }
   }

   private void assertMovieCopies(String classification,
                                  int number, Movie material) {
      assertMaterialCopies(classification, number, material);
      for (Material copy: catalog.get(classification))
         assertEquals(material.getFormat(),
                      ((Movie)copy).getFormat());
   }
}

Listing 5: A Catalog that uses the prototype pattern.

import java.util.*;

public class Catalog {
   private MultiMap<String, Material> materials =
      new MultiMap<String, Material>();

   public void addCopy(String classification) {
      List<Material> copies = materials.get(classification);
      if (copies.isEmpty())
         throw new NoExistingCopyException();

      materials.put(classification, copies.get(0).copy());
   }

   public int size() {
      return materials.valuesSize();
   }

   public void addNew(Material material) {
      materials.put(material.getClassification(), material);
   }

   public List<Material> get(String classification) {
      return materials.get(classification);
   }
}




Page 2 of 3



This article was originally published on April 2, 2008

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.


Thanks for your registration, follow us on our social networks to keep up-to-date