. Java Design Patterns . Java Design Patterns Abstract Factory

Java Design Patterns Abstract Factory

Abstract Factory (AKA Kit) Overview

An abstract factory has sets of methods to make families of various objects.

In this example the AbstractSoupFactory defines the method names and return types to make various kinds of soup.

The BostonConcreteSoupFactory and the HonoluluConcreteSoupFactory both extend the AbstractSoupFactory.

An object can be defined as an AbstractSoupFactory, and instantiated as either a BostonConcreteSoupFactory (BCSF) or a HonoluluConcreteSoupFactory (HCSF). Both BCSF or HCSF have the makeFishChowder method, and both return a FishChowder type class. However, the BCSF returns a FishChowder subclass of BostonFishChowder, while the HCSF returns a FishChowder subclass of HonoluluFishChowder.

AbstractSoupFactory.java - An Abstract Factory

abstract class AbstractSoupFactory {
    String factoryLocation;
    public String getFactoryLocation() {
        return factoryLocation;
    }
    
    public ChickenSoup makeChickenSoup() {
        return new ChickenSoup();
    }
    public ClamChowder makeClamChowder() {
        return new ClamChowder();
    }
    public FishChowder makeFishChowder() {
        return new FishChowder();
    }     
    public Minnestrone makeMinnestrone() {
        return new Minnestrone();
    }
    public PastaFazul makePastaFazul() {
        return new PastaFazul();
    }
    public TofuSoup makeTofuSoup() {
        return new TofuSoup();
    }
    public VegetableSoup makeVegetableSoup() {
        return new VegetableSoup();
    }
}
download source, use right-click and "Save Target As..." to save with a .java extension.

BostonConcreteSoupFactory.java - One of Two concrete factories extending the abstract factory

class BostonConcreteSoupFactory extends AbstractSoupFactory {
    public BostonConcreteSoupFactory() {
        factoryLocation = "Boston";
    }
    public ClamChowder makeClamChowder() {
        return new BostonClamChowder();
    }
    public FishChowder makeFishChowder() {
        return new BostonFishChowder();
    }
}

class BostonClamChowder extends ClamChowder {
    public BostonClamChowder() {
        soupName = "QuahogChowder";
        soupIngredients.clear();        
        soupIngredients.add("1 Pound Fresh Quahogs");
        soupIngredients.add("1 cup corn");    
        soupIngredients.add("1/2 cup heavy cream");
        soupIngredients.add("1/4 cup butter");    
        soupIngredients.add("1/4 cup potato chips");
    }
}

class BostonFishChowder extends FishChowder {
    public BostonFishChowder() {
        soupName = "ScrodFishChowder";
        soupIngredients.clear();        
        soupIngredients.add("1 Pound Fresh Scrod");
        soupIngredients.add("1 cup corn");    
        soupIngredients.add("1/2 cup heavy cream");
        soupIngredients.add("1/4 cup butter");    
        soupIngredients.add("1/4 cup potato chips");
    }
}
download source, use right-click and "Save Target As..." to save with a .java extension.

HonoluluConcreteSoupFactory.java - Two of Two concrete factories extending the abstract factory

class HonoluluConcreteSoupFactory extends AbstractSoupFactory {
    public HonoluluConcreteSoupFactory() {
        factoryLocation = "Honolulu";
    }
    public ClamChowder makeClamChowder() {
       return new HonoluluClamChowder();
    }
    public FishChowder makeFishChowder() {
       return new HonoluluFishChowder();
    }
}

class HonoluluClamChowder extends ClamChowder {
    public HonoluluClamChowder() {
        soupName = "PacificClamChowder";
        soupIngredients.clear();        
        soupIngredients.add("1 Pound Fresh Pacific Clams");
        soupIngredients.add("1 cup pineapple chunks");
        soupIngredients.add("1/2 cup coconut milk");
        soupIngredients.add("1/4 cup SPAM");
        soupIngredients.add("1/4 cup taro chips");
    }
}

class HonoluluFishChowder extends FishChowder {
    public HonoluluFishChowder() {
        soupName = "OpakapakaFishChowder";
        soupIngredients.clear();
        soupIngredients.add("1 Pound Fresh Opakapaka Fish");
        soupIngredients.add("1 cup pineapple chunks");
        soupIngredients.add("1/2 cup coconut milk");
        soupIngredients.add("1/4 cup SPAM");
        soupIngredients.add("1/4 cup taro chips");
    }
}
download source, use right-click and "Save Target As..." to save with a .java extension.

TestAbstractSoupFactory.java - Testing the abstract factory

import java.util.Calendar;

class TestAbstractSoupFactory { 
   public static Soup MakeSoupOfTheDay(AbstractSoupFactory 
                                       concreteSoupFactory)
   { 
       Calendar todayCalendar = Calendar.getInstance();
       //int dayOfWeek = todayCalendar.get(Calendar.DAY_OF_WEEK);
       
       int dayOfWeek = Calendar.TUESDAY;
       
       if (dayOfWeek == Calendar.MONDAY) {
           return concreteSoupFactory.makeChickenSoup();
       } else if (dayOfWeek == Calendar.TUESDAY) {
           return concreteSoupFactory.makeClamChowder();
       } else if (dayOfWeek == Calendar.WEDNESDAY) {
           return concreteSoupFactory.makeFishChowder();
       } else if (dayOfWeek == Calendar.THURSDAY) {
           return concreteSoupFactory.makeMinnestrone();
       } else if (dayOfWeek == Calendar.TUESDAY) {
           return concreteSoupFactory.makePastaFazul();
       } else if (dayOfWeek == Calendar.WEDNESDAY) {
           return concreteSoupFactory.makeTofuSoup();
       } else {
           return concreteSoupFactory.makeVegetableSoup();
       }
   }        

   public static void main(String[] args) 
   {
       AbstractSoupFactory concreteSoupFactory = 
         new BostonConcreteSoupFactory();
       Soup soupOfTheDay = 
         MakeSoupOfTheDay(concreteSoupFactory);
       System.out.println("The Soup of the day " + 
                          concreteSoupFactory.getFactoryLocation() + 
                          " is " + 
                          soupOfTheDay.getSoupName());
 
       concreteSoupFactory = 
         new HonoluluConcreteSoupFactory();
       soupOfTheDay = 
         MakeSoupOfTheDay(concreteSoupFactory);
       System.out.println("The Soup of the day " + 
                          concreteSoupFactory.getFactoryLocation() + 
                          " is " + 
                          soupOfTheDay.getSoupName());
   }
}      
download source, use right-click and "Save Target As..." to save with a .java extension.

Test Results (if run on a Tuesday)

The Soup of the day in Boston is QuahogChowder
The Soup of the day in Honolulu is PacificClamChowder

UML

UML for Abstract Factory

References

online

Portland Pattern Repository

Books

Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides
Java Design Patterns - A Tutorial by James W. Cooper
Sign In
to add your own comment
Comment by ayer Rate this Comment

this is great, but...did I mis something? I couldn't find the definitions for FishChowder and ClamChowder classes...

Comment by Sunny Rate this Comment

Thanks for your efforts.
I believe soup.java should be add to this page to make this example completed.

Comment by Boris Rate this Comment

I just found this site, and I believe that is great. A way that might help to make this cod/design clearer would be:
- Reduce the number of classes (soups) - 2 is enough to understand the idea
- use more generic objects, such as "products" (instead of soups), as too much details can be distracting;
- code could be available for download all at once per pattern, in a zip file for instance - this would allow us to then use our UML tools to see the design aspect of this implementation. I understand that some UML diagrams are being used, but these are not exactly UML compliant, and sometimes can be difficult to understand the degree of relationship between objects.
Apart from this comments, I believe that is good that fact that it provides implementation examples for all the gof4 patterns.