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.
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:
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:
Our ice cream using the factory pattern:
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:
Some classes:
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;
}
}