Implementing Factory Design pattern

Recently I have been reading and exploring about the design patterns- the Factory pattern, Observer pattern and many other popular ones. But while I read those I found I would hardly get any chance to really implement such patterns in my projects. May be my projects don’t need them because they aren’t so complex, or was I wrong? I was reviewing the initial code structure with my team mate. We are writing a fresh new codebase for our client’s multiple websites. My client’s websites are more less same in nature and features, and we felt that writing a core codebase with all common features in a core library would be a good idea. By doing so for each site, we would be extending the classes, components from the core library classes and modify the behaviour if required for each site. If the functionality remains same, classes, objects will be used unmodified directly from base classes. Also we planned to have this library shared between multiple websites of the client. We have also used the Zend Framework, which is being increasily used in many sites and provides an MVC architecture (another nice design pattern).

While I reviewed the initial code structure, we had at the top level the library of Zend Framework and at the same level our Core Library Classes. This was kept independent of any specific website or application so that it can be shared amongst several applications and we have single place to update files during maintenance.

Core Library and Project Structure

These core classes defined the core functionalities and properties of entities in the website. It also included some common components that are used to make web interface. One such component was a DataGrid Class. It is nice class developed by one of our team member encapsulating all the common features and behaviours that we would expect from a Data Grid. We had now a nice component ready to use in all the websites.

Then we had another project setup where these Core Library was included and was actually used to make few functionalities, like a list page which used the DataGrid class from core library. This we were doing to test the structure, and we were still refining the structure. I found that in the application my team mate had made a new class which extended the base DataGrid class.

The sample code is as below.

<?php
class ProjectDataGrid extends DataGrid{
}
?>

and created object of the above class like this

<?php $dg = new ProjectDataGrid(); ?>

And used the methods and properties inherited from the base DataGrid class. Now there is nothing wrong in this, and the page displayed the grid well. But if you observe the above class it does nothing, its just a blank Class which extends the base class. I questioned, why we have created here a dummy class, if it has been unchanged. We could have created rather the object of the Base Class and use it directly, like below

<?php $dg = new DataGrid(); ?>

This also is absolutely fine, if there is no change in the core functionality of the grid.

My friend then reasoned that if in future after we have coded considerable code or say after the project has been delivered, there needs some modification in the functionality of the datagrid, how would we implement that change, if objects of the base class has been used directly? In such a case we would need to create a new class extending the base class, modifying the behaviour in the derived class and then using objects of the new derived class throughout the application. Now this would be a considerable effort and doing this change would be time consuming and error prone, as we would be doing the below, everywhere where DataGrid has been used.

<?php
// $dg = new DataGrid(); commented this, as we now would need  the modified DataGrid.
$dg = new ProjectDataGrid(); //using modified data grid (derived).
?>

Another option would be to change the functionality in the Core Library. Now, this is absolutley not desirable as the functionailty change has been in only one application and not all others. If the change has been made in Core Library Class, it will effect all the other applications using the core library and which might also break them. This is definately not desirable.

His reasoning and understanding was good and valid, and he tried to loose couple the application by creating a dummy class, and using that derived class from the begining in application instead of the core base class, so later changes could be integrated easily.

But i was still not convinced about creating blank dummy classes. There would not be this class alone in an application, but there would be many such classes extending the core classes which we would be creating unnecessarily if there is no functionality change in them within the application. Also its important to keep the application loosely coupled, so future modifications like above are easy to make.

At this very moment I got an idea about implementing the design pattern that I have recently learnt and willing to implement in my projects. The best fit design pattern for this situation is “Factory” design pattern. Factory design pattern proposes a mechanism which would create and return instances/objects of a class whenver a request is maded to the Factory. So the main purpose of Factory would be to manufacture and provide objects.

Instead of directly instantiating a class through “new” keyword, Factory takes up the role which provides you with objects whenever a new one is required. We removed the dummy class and we designed a Factory in our code which would create DataGrid objects. It looked like below

<?php
class Factory{
public static function getDataGrid(){
return new DataGrid();
}
}
?>

We built a class called Factory in our application with a static function ‘getDataGrid’. We kept function static so that we don’t need to create any Factory object unnecessarily before requesting any other object. This function essentialy creates a object of a class and returns it to the caller. So i can now create DataGrid object using Factory like this.

<?php $dg = Factory::getDataGrid(); ?>

If you now observe, my code for instatiating DataGrid object has been centralized to a single location inside the Factory class, instead of spreading out in all places in the application. I have single point of change now.

Now if there is no change in the core functionality of DataGrid class, i can directly create and use object of the base DataGrid class without creating any blank dummy class. And at the same time if i need to modify the core functionality of the DataGrid class within my application in future I can simply create a new class at that time, and change the class name inside the Factory method, like below

<?php
class Factory{
public static function getDataGrid(){
//return new DataGrid();		//disabled this class and..
return new ProjectDataGrid();	//replaced with new class.
}
}
$dg = Factory::getDataGrid(); // now i have object of the new derived class
?>

The above code change would reflect the change in all places where Factory has been used to create the object (and we will make sure that objects are created through Factory only).

The above design pattern, makes our application loosely coupled, and avoids us to create unnecessary blank classes. We would create a derived class only when required instead of creating a dummy derived class everytime. Change of the class would be at the central location so its easy to update the code and less error prone, should we need to create and extend a new class in future.

The above Factory class has been kept simple, for now. We will be revisiting it and optimizing so that it can fit different object manufacturing requests. I see there can be two ways we create a Factory, Factory for each class or a single general Factory having methods which would return objects of different classes, like the one we have described above. This is another design decision and choice and can be based on project requirements and complexity.

I welcome your comments regarding this and any further enhancements that can be done for such situations

  • slier

    now i understand the idea behind factory method
    tq sir