CSC/ECE 517 Fall 2009/wiki3 15 Programming by Assertions

From Expertiza_Wiki
Jump to navigation Jump to search

"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. The Factory Method pattern is a lightweight pattern that achieves independence from application-specific classes. The client programs to the interface and lets the pattern sort out the rest 6

  • 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 flexibility is important.
  • 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.
  • When there is a specific reason why one subclass would be chosen over another. Basically this logic forms part of the Factory Method.
  • When the clients delegates responsibilities to subclasses in parallel hierarchies 6.
  • In test driven environment for the classes to be put under test3.

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

#: 
# A simple static factory method.
from __future__ import generators
import random
##
class Coffee(object):
 # Create based on class name:
 def factory(type):
   #return eval(type + "()")
   if type == "CafeMocha": return CafeMocha()
   if type == "CafeLate": return CafeLate()
   assert 1, "We don't serve this coffee: " + type
 factory = staticmethod(factory)
##
class CafeMocha(Coffee):
 def dark(self): print "CafeMocha.dark" 
 def white(self): print "CafeMocha.white" 
##
class CafeLate(Coffee):
 def dark(self): print "CafeLate.dark" 
 def white(self): print "CafeLate.white" 
##
# Generate coffee name strings:
def caffeeNameGen(n):
 types = Coffee.__subclasses__()
 for i in range(n):
   yield random.choice(types).__name__
##
coffee_name = \
 [ Coffee.factory(i) for i in coffeeNameGen(7)]
##
for coffee in coffee_name:
 coffee.dark()
 coffee.white()
#:~

Factory method in Ruby

class CoffeeFactory  
  def initialize(type)  
     @dark_coffee = self.class.const_get("#{type}Dark")  
     @white_coffee = self.class.const_get("#{type}White")  
  end  
  //
  def new_dark  
     @dark_coffee.new  
  end  
  //
  def new_white  
     @white_coffee.new  
  end  
end  
//
cafe_factory = CoffeeFactory.new('CAFE')  
cafe_dark = cafe_factory.new_dark   
//
late_factory = CoffeeFactory.new('LATE')  
late_white = late_factory.new_white

Factory method in C#

 using System;
 using System.Collections;
 class MainApp
 {
   static void Main()
   {
     // An array of creators 
     Creator[] creators = new Creator[2];
     creators[0] = new ConcreteCreatorA();
     creators[1] = new ConcreteCreatorB();
     //
     // Iterate over creators and create products 
     foreach(Creator creator in creators)
     {
       Product product = creator.FactoryMethod();
       Console.WriteLine("Created {0}", 
         product.GetType().Name);
     }
     //
     // Wait for user 
     Console.Read();
   }
 }
 //
 // "Product" 
 abstract class Product
 {
 }
 //
 // "ConcreteProductA" 
 class ConcreteProductA : Product
 {
 }
 //
 // "ConcreteProductB" 
 class ConcreteProductB : Product
 {
 }
 //
 // "Creator" 
 abstract class Creator
 {
   public abstract Product FactoryMethod();
 }
 //
 // "ConcreteCreator" 
 class ConcreteCreatorA : Creator
 {
   public override Product FactoryMethod()
   {
     return new ConcreteProductA();
   }
 }
 //
 // "ConcreteCreator" 
 class ConcreteCreatorB : Creator
 {
   public override Product FactoryMethod()
   {
     return new ConcreteProductB();
   }
 }
 //
 Created ConcreteProductA
 Created ConcreteProductB

Limitations

In spite of advantages of factory method there are few limitations of factory method.

  • The main limitation is this pattern is very difficult to refactor.
  • Another difficulty is that the subclasses can't be extended as the pattern initializes the constructor as private. Generally the subclasses inherit the superclass constructor but here in this case it can not be done as the superclass constructor is always private.
  • This difficulty can be overcome by changing constructor type from private to protected but the problem is then the subclasses need to re implement all the methods again with same signature.

Conclusion

Index

References

[1] http://wapedia.mobi/en/Creational_pattern - Creational pattern

[2] http://www.artima.com/forums/flat.jsp?forum=17&thread=80613 - Prototype pattern

[3] http://en.wikipedia.org/wiki/Factory_method - Factory method

[4] http://www.allapplabs.com/java_design_patterns/factory_pattern.htm - Factory method

[5] http://sourcemaking.com/design_patterns/factrory_method/c%2523 - Factory method in C#