Factory Method Design Pattern: Creational Pattern

Share the Article

What

Factory method design pattern is a type of creational pattern. This pattern controls the creation of objects. It exposes an interface to the user or client for creating a product.

It hides all details of product and its structure inside the interface. Therefore, the client only needs to pass parameter to the interface to select the type.

Why

In order to understand need of Factory method design pattern lets take an example. This application needs to create a Monitor Screen based on user requirement.

Currently, assume that application only supports flat and curved monitors.

Application without using Factory Method Pattern

#include<iostream> //main header using namespace std;//for namespace enum SCREEN_TYPE { FLAT_SCREEN , CURVED_SCREEN } ; class monitorScreen { public: virtual void screenDispatched()=0; }; class flatScreen: public monitorScreen { public: void screenDispatched() { cout<<"Flat Screen Dispatched"; } }; class curvedScreen: public monitorScreen { public: void screenDispatched() { cout<<"Curved Screen Dispatched"; } }; int main() //Client Code { monitorScreen *m1; SCREEN_TYPE screenType =FLAT_SCREEN ; if( screenType == FLAT_SCREEN) m1 = new flatScreen; else if( screenType == CURVED_SCREEN) m1 = new curvedScreen; m1->screenDispatched(); }

Please note that main function represents client code.

Now with time, the technology changes. Hence, the application needs to support more screen types. For instance, circular, rectangular, 3D, HD screens.

Therefore, the above application should adapt for new requirements. We need to update:

  • Monitor Screen class structure.
  • Main function code (user or client) code .

Updated example

#include<iostream> //main header using namespace std; //for namespace enum SCREEN_TYPE { FLAT_SCREEN , CURVED_SCREEN , 3D_SCREEN, HD_SCREEN } ; class monitorScreen { public: virtual void screenDispatched()=0; }; class flatScreen: public monitorScreen { public: void screenDispatched() { cout<<"Flat Screen Dispatched"; } }; class curvedScreen: public monitorScreen { public: void screenDispatched() { cout<<"Curved Screen Dispatched"; } }; class 3DScreen: public monitorScreen //New type { public: void screenDispatched() { cout<<"3D Screen Dispatched"; } }; class HDScreen: public monitorScreen //New type { public: void screenDispatched() { cout<<"HD Screen Dispatched"; } }; int main() { monitorScreen *m1; SCREEN_TYPE screenType =THREED_SCREEN ; if( screenType == FLAT_SCREEN) m1 = new flatScreen; else if( screenType == CURVED_SCREEN) m1 = new curvedScreen; else if( screenType == 3D_SCREEN) //New code m1 = new ThreeeDScreen; else if( screenType == HD_SCREEN) //New code m1 = new HdScreen; m1->screenDispatched(); }

Clearly, with the traditional approach, we need to adapt both creator class as well as user. This is because, there is tight coupling between user and creator.

Factory Method Design Pattern

Factory method design pattern is the best fit here. Because, it gives us the flexibility of enhancing the creator without much impacting client.

It give us flexibility of adopting Monitor Screen application. Therefore, it supports different monitors without impacting main function much.

How

Lets try to update Monitor Screen application with factory method pattern. Need to follow specific very simple rules for this.

1. Declare Static factory method

Declare this method inside the creator class. This method shall return object of the product class.

monitorScreen* monitorScreen::createMonitorScreen (SCREEN_TYPE screenType);

2. Update Client or user to use factory method

Client shall create desired monitor screen using factory class. He will not instead create the monitor by himself.

monitorScreen *m1=monitorScreen::createScreen(screenType);
UML diagram explaining factory method design pattern

Monitor Screen application with Factory Method Design Pattern

#include<iostream> //main header using namespace std;//for namespace enum SCREEN_TYPE { FLAT_SCREEN , CURVED_SCREEN , 3D_SCREEN, HD_SCREEN } ; class monitorScreen { public: //Factory Method static monitorScreen *createMonitorScreen (SCREEN_TYPE screenType); virtual void screenDispatched()=0; }; class flatScreen: public monitorScreen { public: void screenDispatched() { cout<<"Flat Screen Dispatched"; } }; class curvedScreen: public monitorScreen { public: void screenDispatched() { cout<<"Curved Screen Dispatched"; } }; class 3DScreen: public monitorScreen { public: void screenDispatched() { cout<<"3D Screen Dispatched"; } }; class HDScreen: public monitorScreen { public: void screenDispatched() { cout<<"HD Screen Dispatched"; } }; monitorScreen* monitorScreen::createMonitorScreen (SCREEN_TYPE screenType) { monitorScreen *m1 = NULL; if( screenType == FLAT_SCREEN) m1 = new flatScreen; else if( screenType == CURVED_SCREEN) m1 = new curvedScreen; else if( screenType == THREED_SCREEN) m1 = new ThreeeDScreen; else if( screenType == HD_SCREEN) m1 = new HdScreen; return m1; } int main() { SCREEN_TYPE screenType = 3D_SCREEN ; monitorScreen *m1 = monitorScreen::createMonitorScreen(screenType); m1->screenDispatched(); }

So, if in future we need to update an application for more screens. Then, we simply need to change factory method. There shall be no changes on client side application for creating screen. For instance, suppose now a new screen got added. Only need to change only the factory method and not change in main function(client code)

monitorScreen* monitorScreen::createScreen(SCREEN_TYPE screenType) { monitorScreen *m1 = NULL; if( screenType == FLAT_SCREEN) m1 = new flatScreen; else if( screenType == CURVED_SCREEN) m1 = new curvedScreen; else if( screenType == THREED_SCREEN) m1 = new ThreeeDScreen; else if( screenType == HD_SCREEN) m1 = new HdScreen; else if( screenType == 5D_SCREEN) //New type m1 = new HdScreen; return m1; }

Pros & Cons of Factory Method Design Pattern

Pros

  1. Ownership is with creator class factory method only. So, the client need not bother about creation of objects.
  2. Secondly, the creation of objects and it structure are completely hidden.
  3. Finally, the future update of the application is very easy.

Cons

  1. Every product class needs to have factory method.

Main Funda: The factory method takes the ownership of creation of product.

Advanced C++ Topics

Abstract Factory Design Pattern
Singleton Design Pattern
Lambda in C++11
Lambda in C++17
Thread Synchronization with Mutex
How std::forward( ) works?
How std::move() function works?
What is reference collapsing?

Share the Article

Leave a Reply

Your email address will not be published. Required fields are marked *