Factory Method
Explained
2
Intent
Define an interface for creating an object, but let subclasses decide which class to instantiate.
Factory Method lets a class defer instantiation to subclasses.
a.k.a. Virtual Constructor The main intent of the virtual constructor idiom
in C++ is to create a copy of an object or a new object without knowing its concrete type and this is exactly what the Factory Method does
Can a constructor be virtual?
3
Motivation Frameworks use abstract classes to define and
maintain relationships between objects A framework is often responsible for creating
these objects as well They must instantiate classes but only know
about abstract classes - which they cannot instantiate
Factory method encapsulates knowledge of which subclass to create - moves this knowledge out of the framework
4
Motivation (Cont’d)
Consider a framework for presenting multiple documents to the user
Key abstraction in this framework are Application and Document classes
Both classes are abstract and realized in subclasses
Application class is responsible for managing and creating the Documents as and when required.
5
Motivation (Cont’d)
The particular Document subclass to instantiate is application specific, and
The Application class can’t predict the subclass of Document to instantiate. As it only knows when a new document should be created.
NOT What kind of a Document to create. This creates a dilemma…
6
Motivation (Cont’d)
Factory method solves this problem. It encapsulates the knowledge of which Document to create and moves this knowledge out of the framework.
factory method
7
Motivation (Cont’d) Application subclasses redefine an abstract
CreateDocument operation to return Document subclasses
Once an Application subclass is instantiated, it can then instantiate application specific Documents
We call CreateDocument a factory method as it’s responsible for manufacturing a object.
8
Applicability Use the Factory Method pattern when
A class can’t anticipate the class of objects it must create
A class wants it’s subclasses to specify the objects it creates
Classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate.
9
Structure
10
Participants Product (Document)
defines the interface of objects the factory method creates Concrete Product (MyDocument)
Implements the product interface Creator (Application)
declares the factory method which return a Product type. May also define a default implementation of the factory
method that returns a default ConcreteProduct object May call the factory method to create a Product object.
Concrete Creator (MyApplication) Overrides the factory method to return Concrete Product
11
Collaborations Creator relies on it’s subclasses to define the
factory method so that it returns an instance of the appropriate ConcreteProduct(Subclasses of Product)
12
Consequences Factory methods eliminate the need to bind
application specific classes into your code The code only deals with the Product
interface; therefore it can work with any user defined ConcreteProduct classes.
A potential disadvantage of using Factory pattern is that client also has to subclass the Creator class in order to create a particular ConcreteProduct object.
13
Consequences (Cont’d) Provides hooks for subclasses
Creating objects inside a class with a factory method is always more flexible than creating an object directly
Factory method gives subclasses a hook for providing an extended version of an object
Example: the Document class could define a factory method called CreateFileDialog for opening an existing document.
14
Consequences (Cont’d)
Connects Parallel Class Hierarchies Parallel Class hierarchies result when a class
delegates some of it’s responsibilities to a separate class
Clients can use factory methods to connect between parallel class hierarchies
15
Consequences (Cont’d) The figure class provides a CreateManipulator
factory method that lets clients create a Figure’s corresponding Manipulator
Figure subclasses override this method to return an instance of the required manipulator subclass
Alternatively the Figure class may implement CreateManipulator to return a default manipulator. The figure subclasses may inherit the default.
The figure classes that do so need no corresponding Manipulator subclasses. Hence partially parallel class hierarchies
This is how the factory method defines connection between these class hierarchies
16
Implementation Styles Two Major Varieties
The case when the Creator class is an abstract class and does not provide an implementation of factory method
The case when the Creator class is a concrete class and has a default implementation of the factory method
The first case requires subclasses to define an implementation as there is no reasonable default
In the second case the subclasses or concrete Creator uses factory method primarily for flexibility.
17
Implementation Styles (Cont’d) Parameterized factory methods
create multiple kinds of products the factory method takes a parameter that
identifies the kind of object to create the object share the Product interface
Naming conventions The name of the Factory method in code should
clearly mark its purpose.
18
Implementation So the situation is that you have a set of
related concrete classes and there may be some conditions to call any one of them
19
Implementation (Cont’d) When we see code like this we know that when it comes
to changes and extensions, we will have to re-open this code and examine what needs to be added or deleted.
Often this type of code ends up in several parts of an application making maintenance and updates more difficult and error prone.
By coding to an interface we know we can insulate ourselves with lot of changes occurring down the road
However if you have concrete classes then you might end up in trouble if more concrete classes are added
In other words code would not be closed for modification So what’s the solution?
20
Implementation (Cont’d) Remember the design principle “Identify the
aspects that vary and separate them from what stays the same”
We will now see an example implementation of Pizza shop to illustrate the application of this design principle
We will have a function of OrderPizza() to determine one type of Pizza and run different processes for making a pizza.
21
Implementation (Cont’d)public class Pizza { Pizza pizza; //Declarations public Pizza() { } //Constructor of Pizza //Declarations of Pizza Functions public virtual void Prepare() {} public virtual void Bake() { } public virtual void Cut() { } public virtual void Box() { }//Method of Ordering a Pizza public void OrderPizza() {
pizza = new Pizza(); pizza.Prepare();
pizza.Bake(); pizza.Cut(); pizza.Box(); } //Return only one type of Pizza
22
Implementation (Cont’d) The concrete classes of Pizza like cheese pizza and
pepperoni pizzapublic class CheesePizza : Pizza{ public CheesePizza() { Console.WriteLine("Constructing CHEESE PIZZA"); } public override void Prepare()
{ Console.WriteLine("Preparing CHEESE PIZZA"); } public override void Bake()
{ Console.WriteLine("Baking CHEESE PIZZA"); } public override void Cut()
{ Console.WriteLine("Cutting CHEESE PIZZA"); } public override void Box()
{ Console.WriteLine("Boxing CHEESE PIZZA"); } }
23
Implementation (Cont’d)public class PepperoniPizza : Pizza{ public PepperoniPizza() { Console.WriteLine("Constructing Pepperoni Pizza"); } public override void Prepare()
{ Console.WriteLine("Preparing Pepperoni Pizza"); } public override void Bake()
{ Console.WriteLine("Baking Pepperoni Pizza"); } public override void Cut()
{ Console.WriteLine("Cutting Pepperoni Pizza"); } public override void Box()
{ Console.WriteLine("Boxing Pepperoni Pizza"); } }
24
Implementation (Cont’d) Now we will add code that determines different
types of pizza and then goes about making it. The order pizza function will changepublic void OrderPizza(String type){
if (type.Equals("Cheese")){ pizza = new CheesePizza(); //Calling object of Subclass for
Cheese Pizza } else if (type.Equals("Pepperoni")) { pizza = new PepperoniPizza();//Calling object of Subclass for
Pepperoni Pizza } pizza.Prepare(); pizza.Bake(); pizza.Cut(); pizza.Box(); }
25
Implementation (Cont’d) We have now passed the type of pizza (string
type) to OrderPizza function Based on the type of pizza we instantiate the
correct concrete class and assign it to the pizza instance variable.
Note that each pizza here would have to implement the pizza interface.
So each pizza type knows how to prepare itself.
But the pressure in on to add or subtract pizza types
26
Implementation (Cont’d)public void OrderPizza(String type){ if (type.Equals("Cheese")){ pizza = new CheesePizza(); } else if (type.Equals("Pepperoni")){ pizza = new PepperoniPizza(); }// “here we can add more pizza types” pizza.Prepare(); pizza.Bake(); pizza.Cut(); pizza.Box(); }
This part of code is changing
This part of code is supposed to remain unchanged
27
Implementation (Cont’d) Clearly we can now make out what’s variable
in our code and we need to separate it What we can do is that place the object
creation code into another object (class) whose sole purpose is to create different types of pizza
This object can be called a SimplePizzaFactory Once we have a factory the OrderPizza()
becomes a client of that factory. Anytime it needs a pizza it asks the factory to make one
OrderPizza will get a correct pizza and would call prepare(),bake(),cut() and box()
28
Implementation (Cont’d) Here is the new class SimplePizzaFactory
public class SimplePizzaFactory { public SimplePizzaFactory() { } public Pizza CreatePizza(String type)//This method would be used by all to create
new objects { Pizza pizza = null; if (type.Equals("Cheese")) { pizza = new CheesePizza(); //Calling object of Subclass for Cheese Pizza } else if (type.Equals("Pepperoni")) { pizza = new PepperoniPizza();//Calling object of Subclass for Pepperoni Pizza } return pizza; } }
29
Implementation (Cont’d) The orderpizza method also be moved out of the Pizza class
and would be changed as under
public class PizzaStore { SimplePizzaFactory factory = new SimplePizzaFactory(); //Creates the
factory public PizzaStore() { } public void OrderPizza(String type) { Pizza pizza; pizza = factory.CreatePizza(type); //Get the correct pizza from Factory pizza.Prepare(); pizza.Bake(); pizza.Cut(); pizza.Box(); }//Method of Ordering a Pizza }
30
Implementation (Cont’d)
31
Implementation (Cont’d) Now the Pizza class would be changed as under
public abstract class Pizza //Superclass Pizza { public Pizza() { } //Contructor of Pizza
//Declarations of Pizza Funtions public virtual void Prepare() { } public virtual void Bake() { } public virtual void Cut() { } public virtual void Box() { } }
32
Implementation (Cont’d) The calling program for our codeclass Program { static void Main(string[] args) { PizzaStore pizzastore = new PizzaStore();// The client just
knows the pizza store pizzastore.OrderPizza("Pepperoni");
Console.ReadLine(); } }
33
Quiz # 1 Elements of a Design Pattern with an example Describe Scope Based Design Patterns
Classification?