CSC/ECE 517 Fall 2009/wiki3 15 Programming by Assertions
"Factory method is a type of creational pattern. Like other creational patterns, it deals with the problem of creating objects (products) without specifying the exact class of object that will be created. Be sure to emphasize how it is different from the more general Creator pattern. Also give several examples of how it can be used, and where it provides a more elegant solution than other creational patterns."
Introduction
- What is factory method?
In object oriented language, factory method pattern is a creational design pattern which deals with the mechanism of creating objects of the classes without specifying the exact class of the object.
- What is creational pattern?
In software engineering creational patterns are used to create objects suitable to the situation. In object oriented design object creation may lead to design problems if they are not controlled according to situations. Creational patterns deals with this mechanism. There are a list of different creational patterns available which solves problem of creating objects in different situations. The list includes factory design pattern as well. Here we'll see how factory design pattern is different from other creational design patterns and where it is mostly used.
List of creational patterns
- Factory method pattern: In object oriented design a factory is a place used for creating objects. Factory pattern provides centralize creation of an object of a specific type choosing one of several implementations. It encapsulates the creation of objects. At run time the decision is made about which object to instantiate depending on the situation. So it creates objects without specifying the class of the objects.
- Abstract factory pattern: Abstract factory is the place to take centralize decision of what factory to instantiate. It provides an encapsulation to a group of factories that have common properties. The clients who implement abstract factories doesn't know which concrete object it gets from individual internal factories. The clients only implements the generic interface of these factories. To understand how this pattern is used refer to Abstract factory. This abstraction hides the details of different implementation of objects from their general usage. Factory design pattern is used inherently in this pattern design.
- Prototype pattern: Prototype means making clones. This pattern is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects. The cost of creating new objects is resource intensive job. This pattern gives solution in this scenario where object cloning saves this cost in terms of resources. This pattern is used to avoid building a class hierarchy of factories that parallels the class hierarchy of products. For a detailed understanding of this pattern refer to Prototype pattern.
- Builder pattern: It is a creational pattern which abstracts the object creation pattern. Builder pattern separates the construction of a complex object from its representation so that the same construction process can create different representations. For a detailed understanding of this pattern refer to Builder pattern. This is much more complex object creation pattern than factory method. There may be cases where design starts with factory method and eventually leads to builder pattern according to the flexibility needed in object creation process.
- Singleton pattern: This pattern restricts instantiation of the class to exactly one object. There may be situations where exactly one object of the class is needed. For example server configuration, logger etc where this pattern is used. Other design patterns like builder, prototype or abstract patterns can also use singleton pattern in their implementation. For a detailed understanding of this pattern refer to Singleton pattern.
- Object pool: In object oriented design object creation and destruction after completing all operations on it is an expensive task. For example socket connection, database connection etc. are repetitive tasks but are resource intensive in terms of time. This pattern avoids this expensive acquisition and release of resources by by maintaining an object pool. The clients of the object pool places request when it needs an object and releases the hold on the object after performing desired tasks. Then the released objects are returned back to the object pool for reuse. Objects in object pool are specific type of factory object. It can be used for creating singleton object also.
- Lazy initialization pattern: This pattern deals with the mechanism of delaying the creation of an object until the first time the object is needed. The delay in object creation may be required depending on the situations like the calculation of a value or some other expensive process. This pattern can be used together with factory design pattern to design "lazy factory". To understand how 'lazy factory' works refer to lazy initialization.
Class diagram of Factory Method
When to use Factory Method?
The Factory patterns can be used in following situations:
- When a class does not know which class of objects it is going to create.
- When a class gives the freedom to its subclasses to specify which objects to create.
- Programmers use factory pattern where they have to create an object of any one of sub-classes depending on the data provided. The information about which class object is to create is not known to programmers beforehand and the decision is made at run time depending on the data provided.
Example of factory method
- Factory method in Java
abstract class Coffee { public abstract double getPrice(); } class MochaCoffee extends Coffee { public double getPrice() { return 2.65; } } class CafeLate extends Coffee { public double getPrice() { return 2.10; } } class DarkRoastCoffee extends Coffee { public double getPrice() { return 1.96; } } class CoffeeFactory { public enum CoffeeType { Mocha, CafeLate, DarkRoast } public static Coffee createCoffee(CoffeeType coffeeType) { switch (coffeeType) { case Mocha: return new MochaCoffee(); case CafeLate: return new CafeLate(); case DarkRoast: return new DarkRoastCoffee(); } throw new IllegalArgumentException(coffeeType + " is not an expected coffee type. This " + coffeeType + " is not served."); } } class coffeeLover { /* * Create all available coffees in the coffeeshop and print their prices */ public static void main (String args[]) { for (CoffeeFactory.CoffeeType coffeeType : CoffeeFactory.CoffeeType.values()) { System.out.println("Price of " + coffeeType + " is " + CoffeeFactory.createCoffee(coffeeType).getPrice()); } } }
- Factory method in Python
#: c05:shapefact1:ShapeFactory1.py
# A simple static factory method.
from __future__ import generators
import random
class Shape(object):
# Create based on class name:
def factory(type):
#return eval(type + "()")
if type == "Circle": return Circle()
if type == "Square": return Square()
assert 1, "Bad shape creation: " + type
factory = staticmethod(factory)
class Circle(Shape):
def draw(self): print "Circle.draw"
def erase(self): print "Circle.erase"
class Square(Shape):
def draw(self): print "Square.draw"
def erase(self): print "Square.erase"
# Generate shape name strings:
def shapeNameGen(n):
types = Shape.__subclasses__()
for i in range(n):
yield random.choice(types).__name__
shapes = \
[ Shape.factory(i) for i in shapeNameGen(7)]
for shape in shapes:
shape.draw()
shape.erase()
#:~
- Factory method in Ruby