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

Working With Design Patterns: Abstract Factory, Page 2

  • September 4, 2008
  • By Jeff Langr
  • Send Email »
  • More Articles »

Because the result of applying the abstract factory pattern to create a report should be the same as applying the builder pattern, I built a simple integration test to compare the two reports. The tests in Listing 4 show how clients interact with both the abstract factory and the builder to produce reports.

Listing 4: An integration test.

import static org.junit.Assert.*;
import org.junit.*;
import builder.*;
import domain.*;

public class FactoryTest {
   private Catalog catalog;

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

   @Test
   public void compareWebReports() {
      CatalogReportFactory factory =
         CatalogReportFactory.create(catalog, Platform.WEB);
      CatalogReportDirector director =
         new CatalogReportDirector(catalog);

      assertEquals(director.generate(new HtmlCatalogBuilder()),
                   factory.generate());
   }

   @Test
   public void compareDesktopReports() {
      CatalogReportFactory factory =
         CatalogReportFactory.create(catalog, Platform.DESKTOP);
      CatalogReportDirector director =
         new CatalogReportDirector(catalog);

      assertEquals(director.generate(new PrintCatalogBuilder()),
                   factory.generate());
   }

   private Catalog createCatalog() {
      Catalog catalog = new Catalog();
      catalog.add(new Book("QA234.543.34", "Java Puzzlers",
                           "Bloch, Joshua", "2006"));
      catalog.add(new Book("QA234.543.33", "Agile Java",
                           "Langr, Jeff", "2005"));
      catalog.add(new Movie("ZZ234", "Fight Club",
                            "Fincher, David", "1999"));
      catalog.add(new Book("QA234.543.35", "Clean Code",
                           "Martin, Robert C.", "2008"));
      catalog.add(new Movie("ZZ2888", "A Clockwork Orange",
                            "Kubrick, Stanley", "1971"));
      catalog.add(new Book("QA234.543.399",
                           "Working Effectively With Legacy Code",
                           "Feathers, Michael", "2004"));
      catalog.add(new Book("QA234.543.452", "Secrets of Consulting",
                           "Weinberg, Gerald", "1995"));
      catalog.add(new Movie("ZZ234", "Kill Bill: Vol. 1",
                            "Tarantino, Quentin", "2003"));
      return catalog;
   }
}

The static create method defined on CatalogReportFactory is in itself a factory method. Its job is to return a factory specific to the request of the client. This routing of a client request to an appropriate factory is the heart of the abstract factory pattern. Listing 5 shows the CatalogReportFactory implementation.

Listing 5: CatalogReportFactory.

import java.util.*;
import domain.*;

public abstract class CatalogReportFactory {
   protected final Catalog catalog;

   public static CatalogReportFactory create(Catalog catalog,
                                             Platform platform) {
      if (platform == Platform.WEB)
         return new HtmlCatalogReportFactory(catalog);
      return new PrintCatalogReportFactory(catalog);
   }

   public CatalogReportFactory(Catalog catalog) {
      this.catalog = catalog;
   }

   public String generate() {
      Report report = new Report();
      createReportHeader().appendTo(report);
      for (Material material: sortedCatalog())
         createDetailRecord(material).appendTo(report);
      createSummary().appendTo(report);
      return report.toString();
   }

   private List<Material> sortedCatalog() {
      return new MaterialSorter(catalog.materials()).sort();
   }

   abstract protected ReportComponent createSummary();
   abstract protected ReportComponent
      createDetailRecord(Material material);
   abstract protected ReportComponent createReportHeader();
}

The abstract methods defined on CatalogReportFactory are placeholders for a family of related factories. Each CatalogReportFactory implementation is required to provide factory implementations that can produce headers, detail records, and summaries. The factory implementation that produces HTML reports appears in Listing 6. (In case you're interested, the MaterialSorter code appears in Listing 7.)





Page 2 of 4



Comment and Contribute

 


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

 

 


Sitemap | Contact Us

Rocket Fuel