CSC/ECE 517 Fall 2012/ch2b 2w36 av
Factory Method pattern and the related patterns (Template, Prototype)
Factory Method
Factory method pattern is an Object Oriented Programming concept in which objects can be created without specifying the class to which they belong.Factory method pattern implement the concept of using an object to generate other objects.[1]Factory method is thus a type of creational pattern. An interface is defined for object creation. However the subclasses decide which class they want to instantiate. Factory methods thus abstract object instantiation from the client. [7]
The new operator is used in languages like Java to create an object. However in this case the object creation details are not encapsulated. Factory method allows a client to request for an object so that the object creation is encapsulated. Factory method uses inheritance for object creation. The superclass has ‘placeholders’ for the steps involved in object creation. The actual details of the object creation are specified in the subclass.[4]
Use of factory method pattern makes the code more flexible to change. In factory method pattern, interface is used to create an object and the actual instantiation of objects is deferred to subclasses that implement this interface. New classes can be added that implement this interface. In this way it becomes easy to add new concrete classes with minimal changes to the classes that use these objects.[head_first_design_pattern]. Factory method can be used when a class does not know the type of objects that it needs to create[7]
UML Diagram for Factory Method Pattern
In the UML diagram on the right, Product is the interface for the type of object created by the factory method. The Product interface is implemented by ConcreteProduct. The factory method which returns an object of type Product, is declared in Creator. The factory method is overridden inside ConcreteCreator to return an instance of ConcreteProduct.
Code Example
This example has been taken from [4]
public interface ImageReader { public DecodedImage getDecodedImage(); } public class GifReader implements ImageReader { public GifReader( InputStream in ) { // check that it's a gif, throw exception if it's not, then if it is decode it. } public DecodedImage getDecodedImage() { return decodedImage; } } public class JpegReader implements ImageReader { //... }
In the example above the ImageReader interface is defined. In this interface, a method getDecodedImage is defined that should return a decoded image. However this image may have been encoded in any format for example GIFF or JPEG. Therefore the functionality of actually decoding the image is implemented inside two classes GifReader and JpegReader . In this way, the responsibility of creating objects decoded in the appropriate format has been delegated to the subclass implementing the interface.
Template Pattern
Template method pattern is used to specify the format of an algorithm. The basic skeleton of an algorithm is defined in the base class using abstract operations. Subclasses override these abstract operations in order to provide concrete behaviour. In this way, two different subclasses may have different implementations of the abstract functions, but the overall structure of the algorithm will remain same[8].Template method pattern is a behavioural design pattern[9]. Template method pattern helps to avoid code duplication and aids in code reuse[10]
UML Diagram for Template Method Pattern
In the UML diagram on the right, abstract primitive operations are defined for which the subclasses provide the implementation. Template method is implemented which specifies the structure of the algorithm. The primitive operations are called within this template method. The ConcreteClass provides subclass specific implementation for the primitive operations.
Code Example
This example has been taken from [10]
public abstract class TextDocument { public final void printPage () { Document document = createDocument(); document.printTextHeader(); System.out.println(document.body()); document.printTextFooter(); } public abstract Document createDocument(); public abstract void printTextHeader(); public abstract void printTextFooter(); ... }
public class PlainTextDocumentBuilder extends TextDocument { public PlainTextDocumentBuilder(InputStream in){ //check that it is an Plain text document or throw error } public Document createDocument() { return new PlainTextDocument(); } public void printTextHeader () { // Code for header plain text header here. } public void printTextFooter () { // Code for header plain text footer here. } ... }