CMPT 300 Design Patterns
May 2007

Factory Pattern


<< lab4.zip >>

The intent behind the Factory pattern  is to build an interface for object creation, but allow subclasses decide which class to instantiate.

Consider how we may make different ice cream cones:

             IceCream cone;

        if (type.equals("Chocolate"))
            cone = new Chocolate();
        else if (type.equals("Strawberry"))
            cone = new Strawberry();
        else if (type.equals("Vanilla"))
            cone = new Vanilla();

        cone.scoop();

        return cone;


Whenever there is a switch or multiple if-else statements, you have a good candidate for applying the Factory pattern.

An important object-oriented principle is:
Find what varies and encapsulate it.
The code that varies from above is highlighted in blue. (It varies because we may want to make additional ice cream flavors in the future. However, for all flavors of ice cream, we still have to scoop it.)

            IceCream cone;

        if (type.equals("Chocolate"))
            cone = new Chocolate();
        else if (type.equals("Strawberry"))
            cone = new Strawberry();
        else if (type.equals("Vanilla"))
            cone = new Vanilla();


        cone.scoop();

        return cone;


An ice cream factory:
- IceCreamFactory.java

An ice cream store:
- IceCreamShopV1.java

The benefit of moving the if-else-if statements to the factory is that we have decoupled the responsibility of making ice cream from the store (which sells it.) If we add new flavors of ice cream, we only have to change the factory, not anything else. A second benefit is we could have different types of factories making ice cream, and pass the different factory to the IceCreamShop constructor.

To use it:

IceCreamFactory factory = new IceCreamFactory();
IceCreamShopV1 shop = new IceCreamShopV1(factory);
     
shop.orderCone("Chocolate");



Another alternative is to allow ordering and making the cone in the same class, but allow subclasses to determine how to actually make and serve the ice cream.

- IceCreamShop.java

This abstract class uses a consistent technique for ordering a cone - orderCone() - but allows  classes that extend this abstract class to determine how to get the ice cream - getIceCream().

An implementation of IceCreamShop:

- BenAndJerry.java


A simple code example illustrating how we use the factory:

        IceCreamShop bAndJ = new BenAndJerry();
        IceCream cone;
       
        cone = bAndJ.orderCone("Cherry Garcia");
        System.out.println("Enjoying some " + cone.getDescription() + " which costs " + cone.cost());


This is known as the Factory Method pattern. We are applying the pattern to the getIceCream() method.

The general Factory Pattern in UML:

Factory

Our ice cream using the factory pattern:

Factory

The benefits of this approach are:

(1) The client creates an instance of the factory and orders an ice cream cone from the factory. We have separated object creation from the client.

(2) If we create new types of ice cream, we only need to change the affected factory. (i.e. Ben and Jerry's may offer Sublime Orange, while Dairy Queen takes the drastic plunge and offers chocolate chip. We only need to change the associated factory for the new flavor of ice cream.)


The Lab Part I

1. Write a new class that extends IceCreamShop called DairyQueen. Dairy queen serves chocolate, strawberry, and vanilla (which are the flavors from the Decorator lab, so you don't have to create these.)

2. Write a test class called LetsEat.java. This is based on the code shown above that illustrates how to use the factory. Your code will create an instance of DairyQueen and order a chocolate and strawberry cone.

3. Hmmmm .... could we decorate an ice cream cone as well? If so, how?


The Lab Part II

Sorting algorithms may be classified as either recursive (i.e. Quicksort, Shellsort) or non-recursive (i.e. Selection sort, Insertion sort)

This leads to the following:

Factory



Some classes:

- SortingAlgorithm.java

- SortFactory.java

- SelectionSort.java

A client would be able to generate a factory and sort a list of items using the following:

                    String[] elements = {"beta", "chi","alpha","zeta", "nu","mu"};
        SortFactory factory = new NonRecursive();
        factory.setFactory("Selection");
       
        SortingAlgorithm algorithm = factory.getAlgorithm();
       
        algorithm.sort(elements);
       
        for (int i = 0; i < elements.length; i++)
            System.out.println(elements[i]);



Complete the remaining code files. This includes

(1) NonRecursive class;

(2) Insertion class;

(3) Some test code that illustrates using both the selection and insertion sorting algorithms.

(You do not have to worry about the recursive factory or  recursive sorting algorithms.)

The pseudo-code for the insertion sort is

public void insertionsort(Object[] items) {
                int j;
                for (int p = 1; p < items.length; p++) {
                        Object temp = items[p];

                        for (j = p; j > 0 && items[j-1] > temp; j--)
                                items[j] = items[j-1];

                        items[j] = temp;
                }
}