CSC/ECE 517 Fall 2009/wiki3 ksm 6: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
No edit summary
Line 58: Line 58:


* It does not always call a constructor in the creation of a new product.
* It does not always call a constructor in the creation of a new product.


='''Example'''=
='''Example'''=

Revision as of 21:59, 18 November 2009

The Factory Design Pattern And Its Application

Introduction

A programmer, at the time of designing, usually is concerned about the behavior. But other aspects such as the availability of a particular object at the time when it is required also need to be considered. The rules of creation should be followed. Sometimes, the developers intermix the management of object creation with object instantiation. Using same code for object creation as well as object instantiation, can lead to complexity of code. It has to keep a track of object creation, construction parameters, as well as the use of those objects after creation. This leads to several consequences such as reducing coupling as well as selection of an instantiation scheme early. To address these issues, Factories are used which help to keep the objects cohesive, testable and decoupled. The design becomes flexible and the problem can be split into chunks of manageable pieces.


Overview

In this article,we are going to discuss about Factory method Pattern. We will first look at the objectives of Creational patterns. Then we will have a look at different Creational patterns. We will try to find out how and why the Factory Method Pattern has an edge over other Creational patterns. How Factory method design pattern is implemented in some Object Oriented languages providing an elegant solution to a problem. Finally we will discuss about the advantages of the Factory Method pattern.


Features

Their are 23 GoF patterns which have been divided into three broad categories namely:

  • Creational Patterns - These patterns are used in the creation of new objects. They help in hiding the details of object instantiation from the code that is using those objects. Thus making the system independent of the way the objects have been created. The biggest advantage is that it helps in providing a high cohesion and low coupling between the objects and their users.

The Creational patterns are used in the creation of objects requiring to make decisions. They help us in encapsulating dynamic decisions regarding the instantiation of a class or the delegation of responsibilty to objects. Sometimes we have to make a choice when we can use more than one creational pattern to a situation. While at times, we can combine multiple patterns simultaneously so that we can use them to our own advantage. Their general classification is:

  • The Factory Method Pattern - It is a way by which an object can start the creation of other objects without knowing about their classes. The methods on the factory are used to return objects that can be used to implement a given interface. The user only has idea about the interface.

For Example: The following code implements factory method for instantiating appropriate document types. The client has no knowledge of the type of document being created.

                                       public class DocumentFactory{
                                     public static Document getDocument() {
                                        Document doc = null;
                                        if (DocumentType.Word==type){
                                         doc = new WordDocument();
                                   } else if (DocumentType.STAROFFICE==type){
                                          doc = new StarOfficeDocument();
                                        }
                                                  return doc;
                                               }
                                                   } 


  • Abstract Factory Pattern - It is used in creation of different objects by objects without knowing the classes of objects being created. It is very helpful in working with different complex external entities like (different windowing systems) with similar functionality.

For Example: We have to create a user interface framework that can be used to work on top of multiple operating systems. This is done using an abstract class for each type of widget and then write a concrete subclass for each class (for each supported platform).

  • The Builder Pattern - It is used in determining the class of an object. It helps in separating out the construction of a complex object from its use. Thus helps the client in specifying the required type of object and its content. However it does not need to know the details about the construction and initialization of the object.
  • The Prototype Pattern - This Pattern is used in creation of customized objects based on the prototype of the requirement. This pattern describes how a new object can be created based upon the customization of an object that already exists.
  • The Singleton Pattern - This pattern consists of a class that can have only one object constructed for it. It is not possible to have more than one instance within the same virtual machine. It is used in sharing of a common object by multiple objects without even knowing if it already exists. Factories are often accessed with the Singleton Pattern

The Factory method Pattern has several variations depending on the requirement:

  • The Factory method can take parameters and thus can be used to create different type of objects based on the parameters.
  • The factory method in the superclass does not need to be abstract. It can be used to create a default product. So, the subclasses can just override the factory method if they want to create a different kind of product.
  • It does not always call a constructor in the creation of a new product.


Example

Java

Let us take an example in which, we have to draw a polygon. The user has to click on the canvas to select the polygon after which the polygon that corresponds to the selected tool is drawn. We are mainly concerned with the code for MouseListener that reacts to the mouse clicks that take place on the canvas. The code can be written in the following way :

                                           public void mouseclicked(MouseEvent e)
                                            {
                                            if(..currentTool is a square..)
                                            else if(..currentTool is triangle..)
                                            elseif(..current tool is rectangle..)
                                            }

Here we are using conditional statements in creation of the polygons. However, this solution is not very elegant.The code can also be written in a way which is more elegant. We can design the selected tool which can act as a factory that can be used to create the polygon corresponding to the selected tool. To do this, we need to add the following method to the Tool class:

                                            public Polygon createPolygon(Point center)

This method creates a polygon of the selected type with the given center. The mouseClicked method can then be modified as :

                                            public void mouseClicked(MouseEvent e)
                                            {
                                            ..get centerPoint..
                                            Polygon p = currentTool.createPolygon(centerPoint);
                                            ..add p to the canvas..
                                             }

We can clearly see that no conditionals are required. We have added a Factory method which is createPolygon method. It has created obect which can be used by MouseListener. The createPolygon method is made abstract in the Tool class since the Tool class has no idea about which type of polygon is to be created. Then subclasses of Tool clas such as SquareTool, TriangleTool, RectangleTool can be created each of them using the createPolygon method to create appropriate type of object.

As another example, we can consider the java.util.Collection interface and java.util.AbstractCollection class. All classes in the java.util that implement the Collection interface package have a superclass AbstractCollection. The AbstractCollection class can implement almost all the methods of Collection interface. It creates iterators while implementing the methods, but does not know the subclass of iterator which is to be created. For each subclass, a different iterator is used. The Factory Method pattern provides a factory method called iterator in the AbstractCollection class. So, the methods of AbstractCollection class can use that method when they need an iterator method while leaving its implementation to the subclasses of the AbstractCollection class.

Another use can be in the problem of creating objects when there have to be some considerations regarding the creation logic. The creation responsibilities have to be separated so as to provide a better cohesion. The solution can be to create a pure Fabrication object that can handle the creation.


C#

A good Example of Factory Method in C# is the Enumerators in the .NET FCL. The GetEnumerator() methods can be considered as good examples of the Factory Method Pattern. These methods help the caller to create objects without knowing about their classes. C# applies the principle of Factory Method pattern (i.e the creator does not need to know which class to instantiate to collection enumerators) so that the foreach statement can be used with any collection. For Example : consider the following code-

                                        using System;
                                       using Machines;
                                      using System.Collections;
                                      class ShowEnumeration
                                          {
                                       static void Main( )
                                             {
                                     Machine[] machines =
                                    {new Machine(1) , new Machine(2) } ;
                                IEnumerator e = machines. GetEnumerator() ;
                                        while (e.MoveNext() )
                                               {
                                     Machine m = (Machine) e.Current;
                                        Console. WriteLine(m.ID) ;
                                              }
                                           }
                                            }

C# links the foreach statement to the GetEnumerator() method. Thus we can use any class that can implement GetEnumerator() in a foreach statement. The following code is shorter than the previous one although with identical implementation.

                                            using System;
                                           using Machines;
                                      class ShowEnumeration2
                                            {
                                            static void Main( )
                                                {
                                          Machine[] machines =
                                       {new Machine(1) , new Machine(2) } ;
                                          foreach (Machine m in machines)
                                                {
                                        Console.WriteLine(m.ID);
                                          }
                                           }
                                            }

Thus, the foreach statement is not knowing about the type of enumerator that can be used for enumerating a collection. But Collections can specify as well as instantiate any appropriate enumerator. So, each GetEnumerator() of collection class can create an appropriate enumerator thus isolating clients from the knowledge of which class they need to instantiate.


Advantages

  • This pattern is useful in situations when a class needs to create objects but does not know its class. So it leaves the implementation of those objects to its subclasses.
  • The pattern has a simple implementation just by using a factory method in creation of objects instead of using constructors to create objects.
  • The Factory method pattern creates an object in such a way that it reduces coupling between the creator and the class which is being created. The creator is the Factory and the class being created is the Product. The abstract Factory class does not have any idea about the subclasses of the Product that the create method is creating.
  • It helps in creating a framework in which an abstract class using some methods to do some task and then leaving the implementation of those methods to the subclasses. Thus, subclasses can use these methods to implement a specific implementation according to their behavior.
  • The subclasses can create different objects by overriding the factory method.


Links


Referances

  • Object Oriented Design using Java by Dale Skrien(Examples)
  • Design Patterns Explained: A New Perspective on Object-Oriented Design, Second Edition ,By: Alan Shalloway; James R. Trott.

ISBN-978-0-321-24714-8

  • Patterns in Java Vol. 1 /: A Catalog of Reusable Design Patterns Illustrated With UML by Grand, Mark.
  • Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development, Third Edition
  • Design Patterns in C# By: Steven John Metsker
  • Guide to the Unified Process Featuring UML, Java, and Design Patterns Springer Professional Computing by Hunt, John.