Designing “The Factory Pattern”
Demystifying Factory Design Pattern:
“Patterns identify and specify abstractions that are above the level of single classes and instances, or of components.”
The avid readers of our blog can easily conclude that these Patterns are not trivial and they are not represented by features that are built into the language unlike a feature like Inheritance. Hence we say, a Pattern is a proven solution to a problem in a specific context. To put it across in simple words, it’s like a recipe of your Grandma’s Thanksgiving Turkey! After so many trials she found a perfect way, the proper ingredients which makes the Turkey so delicious!
So what are Design Patterns? These are nothing but Elements of Reusable Software and as the famous literature on design patterns, classifies patterns into three types viz. creational, structural and behavioral.
Prior to delving deeper into the esoteric world of these patterns, it’s worthwhile to touch briefly upon what a Creational Pattern is. A creational pattern gives control over instantiation of objects. Using this type of pattern the programmer doesn’t need to instantiate objects directly. They give the program the ability to decide which objects need to be created for a given case.
We have already discussed, at length, a pattern belonging to this type – ‘The Singleton Pattern’. Over the course of this blog, we will examine one of the most commonly used creational design patterns, ‘The Factory Pattern’.
Factory Pattern: A Quintessential Creational Pattern
A Factory pattern is one that only returns instances of several possible classes depending on the data given to it. As with other design patterns, there are countless variations of the Factory pattern, although most variants typically use the same set of primary factors, a client, a factory, and a product. The client is an object that requires an instance of another object (the product) for some purpose. Rather than creating the product instance directly, the client delegates this responsibility to the factory. Once invoked, the factory creates a new instance of the product, passing it back to the client. Put simply, the client uses the factory to create an instance of the product. The following figure shows this logical relationship between these elements of the pattern.
Wondering how and when to Use the Factory Pattern?
Having understood in theory what a factory pattern is all about, the next logical question is how and when we can use this. The main goal of this pattern is to encapsulate the creational procedure that may span different classes into one single function. By providing the correct context to the factory method, it will be able to return the correct object. Thus, the best time to use the factory method pattern is when you have multiple different variations of a single entity. Let’s say you have a class called Shape; this class has different variations, such as Circle Shape, Rectangular Shape and Square Shape. Depending on the requirement, you may need to create different Shapes —this is where you can use a factory to create the Shapes for you!
Use a factory only when you need extra control with object creation, in a way that couldn’t be done with constructors.
Factories have the possibility of caching for example. Another way to use factories is in a scenario where you do not know the type you want to construct. Often you see this type of usage in plug-in factory scenarios where each plug-in must derive from a base class or implement some kind of interface. The factory creates instances of classes that derive from the base class or that implement the interface.
[ More Design Patterns – Simplifying Coding with the Decorator Design Pattern!]
Factory Design Pattern: An object oriented design perspective
• Each time we use the “new” command, we break encapsulation of type
• Circle circle = new Round Circle ();
• Even though our variable uses an “interface”, this code depends on “Round Circle”
• In addition, if you have a code that instantiates a particular subtype based on the current state of the program, then the code depends on each concrete class.
if (shapes) {
Return new Round Circle ()
} else {
return new Circle ();
}
Obvious Problems: Needs to be recompiled each time dep. changes; add new classes, change the code; remove existing classes and modify the code.
The example gets sweeter: Let’s discuss it over a slice of Pastry
• We have a Pastry Corner program that wants to separate the process of creating a Pastry from the process of preparing/ordering a Pastry
• Initial Code: mixes the two processes
PublicclassPastry Corner {
Pastry orderPastry (String type) {
Pastry pastry;
if(type.equals(“BlackForest”)) {
pastry = newBlackForest ();
} —————————————> Creation
elseif(type.equals(“Vanilla”)) {
pastry = newVanillaPastry();
} elseif(type.equals(“Chocolate”)) {
pastry = newChocolate ();}
pastry. Prepare();
pastry.bake();
pastry.cut();
pastry.box();
return
pastry;
}} —————————————> Preparation
Encapsulate Creation Code: Encapsulation Mechanism
• A simple way to enc apsulate this code is to put it in a separate class
• That new class depends on the concrete classes, but those dependencies no longer impact the preparation code
Publicclass Pastry Corner {
PrivateSimple Pastry Corner Factory factory;
Public Pastry Corner (Simple Pastry Corner Factory factory) {
this.factory = factory;
}
Public Pastry order Pastry (String type) {
Pizza Pastry = factory.create Pastry (type);
Pastry.prepare();
Pastry.bake();
Pastry.cut();
Pastry.box();
return Pastry;}}
publicclassSimple Pastry Factory {
public Pastry create Pastry (String type) {
if(type.equals(“BlackForest”)) {
returnnewBlackForest();
}
elseif(type.equals(“Vanilla””)) {
returnnewVanilla Pastry “();
} else if (type. equals (“Chocolate”)) {
returnnewChocolate();
}}}
Class Diagram for New Solution
While this is nice, it’s not as flexible as it can potentially be: to increase flexibility we need to look at one more part of Factory design patterns: The Factory Method
Simple factory Method: Encapsulates object creation in a static method.
A static method in a class which creates an object and returns the instance of a class!! So instead of creating an object you will call this method which gives you the instance of controller class.
•To demonstrate the factory method pattern, the pastry store example evolves to include the notion of different franchises that exist in different parts of the cities (Pune, Mumbai, and Bangalore).
•Each franchise needs its own factory to match the proclivities of the locals.
•However, we want to retain the preparation process that has made Pastry Store such a great success.
•The Factory Method Design Pattern allows you to do this by placing abstract, “code to an interface” code in a super class placing object creation code in a subclass Pastry Store becomes an abstract class with an abstract create Pastry() method. We then create subclasses that override create Pastry() for each region
New Pastry Corner Class:
Public abstract class Pastry Corner {
Protected abstract create Pastry (String type);
Public Pastry order Pastry (String type) {
Pastry pastry = create Pastry (type);
pastry.prepare(); ——————————–> Beautiful Abstract Class!
pastry.bake();
pastry.cut();
pastry.box();
return
pastry;
}}
This class is a (very simple) OO framework. The framework provides one service “prepare pastry”. The framework invokes the create Pastry () factory method to create a pastry that it can prepare using a well-defined, consistent process.
A “client” of the framework will subclass this class and provide an implementation of the create Pastry () method.
Any dependencies on concrete “product” classes are encapsulated in the subclass.
Huh…Tired??? We would not overwhelm you with more information at this point of time. We will discuss other patterns like: Observer, Strategy, Template Method, and Abstract which are famous outside non-Object oriented programming in the series of blogs to follow soon.
P.S.: User discretion is required when you use these design patterns, always make sure that you’re trying to solve the correct problem. As I mentioned previously, these design patterns are a double-edge sword: if used in the wrong context, they can potentially make things worse; but if used correctly, they become indispensable.
Some Interesting reads from the Cloud World :
1. Optimize Big Data Analytics with a Complete Guide to Amazon Cloud’s EMR
2. AWS Cloud for Start-ups Jump Start Package at just $99.99
3. Why is Cloud Computing Big Data’s Best Friend? Hadoop in the Clouds to Answer your Doubts!
4. Building a Live AWS Kinesis Application – The Producer Class, Put Constructor & more…