
- C++ Home
- C++ Overview
- C++ Environment Setup
- C++ Basic Syntax
- C++ Comments
- C++ Hello World
- C++ Omitting Namespace
- C++ Tokens
- C++ Constants/Literals
- C++ Keywords
- C++ Identifiers
- C++ Data Types
- C++ Numeric Data Types
- C++ Character Data Type
- C++ Boolean Data Type
- C++ Variable Types
- C++ Variable Scope
- C++ Multiple Variables
- C++ Basic Input/Output
- C++ Manipulators
- C++ Modifier Types
- C++ Storage Classes
- C++ Constexpr Specifier
- C++ Numbers
- C++ Enumeration
- C++ Enum Class
- C++ References
- C++ Date & Time
- C++ Operators
- C++ Arithmetic Operators
- C++ Relational Operators
- C++ Logical Operators
- C++ Bitwise Operators
- C++ Assignment Operators
- C++ sizeof Operator
- C++ Conditional Operator
- C++ Comma Operator
- C++ Member Operators
- C++ Casting Operators
- C++ Pointer Operators
- C++ Operators Precedence
- C++ Unary Operators
- C++ Scope Resolution Operator
- C++ Control Statements
- C++ Decision Making
- C++ if Statement
- C++ if else Statement
- C++ Nested if Statements
- C++ switch Statement
- C++ Nested switch Statements
- C++ Loop Types
- C++ while Loop
- C++ for Loop
- C++ do while Loop
- C++ Foreach Loop
- C++ Nested Loops
- C++ break Statement
- C++ continue Statement
- C++ goto Statement
- C++ Strings
- C++ Strings
- C++ Loop Through a String
- C++ String Length
- C++ String Concatenation
- C++ String Comparison
- C++ Functions
- C++ Functions
- C++ Multiple Function Parameters
- C++ Recursive Function
- C++ Return Values
- C++ Function Overloading
- C++ Function Overriding
- C++ Default Arguments
- C++ Arrays
- C++ Arrays
- C++ Multidimensional Arrays
- C++ Pointer to an Array
- C++ Passing Arrays to Functions
- C++ Return Array from Functions
- C++ Structure & Union
- C++ Structures
- C++ Unions
- C++ Class and Objects
- C++ Object Oriented
- C++ Classes & Objects
- C++ Class Member Functions
- C++ Class Access Modifiers
- C++ Static Class Members
- C++ Static Data Members
- C++ Static Member Function
- C++ Inline Functions
- C++ this Pointer
- C++ Friend Functions
- C++ Pointer to Classes
- C++ Constructors
- C++ Constructor & Destructor
- C++ Default Constructors
- C++ Parameterized Constructors
- C++ Copy Constructor
- C++ Constructor Overloading
- C++ Constructor with Default Arguments
- C++ Delegating Constructors
- C++ Constructor Initialization List
- C++ Dynamic Initialization Using Constructors
- C++ Inheritance
- C++ Inheritance
- C++ Multiple Inheritance
- C++ Multilevel Inheritance
- C++ Object-oriented
- C++ Overloading
- C++ Polymorphism
- C++ Abstraction
- C++ Encapsulation
- C++ Interfaces
- C++ Virtual Function
- C++ Pure Virtual Functions & Abstract Classes
- C++ Design Patterns
- C++ Creational Design Patterns
- C++ Singleton Design Pattern
- C++ Factory Method Design Pattern
- C++ Abstract Factory Pattern
- C++ File Handling
- C++ Files and Streams
- C++ Reading From File
- C++ Advanced
- C++ Exception Handling
- C++ Dynamic Memory
- C++ Namespaces
- C++ Templates
- C++ Preprocessor
- C++ Signal Handling
- C++ Multithreading
- C++ Web Programming
- C++ Socket Programming
- C++ Concurrency
- C++ Advanced Concepts
- C++ Lambda Expression
- C++ unordered_multiset
Factory Method Pattern in C++
The Factory Method Pattern is a creational design pattern that defines an interface for creating an object. It allows its subclasses to change the type of object that will be created.
For example, imagine you are creating an employee management system for your comapany, and there are different types of employees such as full-time employees, part-time employees, and contract employees. Each type of employee has different attributes and behaviors. Instead of creating a separate class for each type of employee, you can use the factory method pattern to create a single interface for creating employees and then let the subclasses decide which type of employee to create.
So, instead of calling new at the client side, we can just call a factory method which will return the object of the desired type.
Implementation of Factory Method Pattern in C++
There are ways to implement the Factory Method Pattern in C++. Some of the important and common implementations are:
- Factory Method (GoF official one)
- Simple Factory (static method)
- Registry-based Factory (parameterized)
Let's discuss each of these implementations in detail.The important point to note is that the Factory Method Pattern is often used in conjunction with other design patterns such as Singleton, Abstract Factory, and Builder patterns.
Also, the type of implementation you choose will depend on the specific requirements of your application and the complexity of the object creation process.
Implementation of Factory Method by the Official GoF Way in C++
This is an official implementation of the factory method pattern as described in the Gang of Four book. In this approach, we create an abstract class that defines the factory method and then create concrete subclasses that implement the factory method to create specific types of objects.
Let's take an example of a car factory. We have an abstract class CarFactory that defines the factory method createCar(). Then, we create concrete subclasses such as SUVFactory and SedanFactory that implement the factory method to create specific types of cars.
Example of Factory Method Pattern in C++
Following is the code implementation of Factory Method Pattern in C++ â
#include <iostream> #include <string> class Car { public: virtual void drive() = 0; virtual ~Car() {} }; class SUV : public Car { public: void drive() { std::cout << "Driving an SUV" << std::endl; } }; class Sedan : public Car { public: void drive() { std::cout << "Driving a Sedan" << std::endl; } }; class CarFactory { public: virtual Car* createCar() = 0; virtual ~CarFactory() {} }; class SUVFactory : public CarFactory { public: Car* createCar() { return new SUV(); } }; class SedanFactory : public CarFactory { public: Car* createCar() { return new Sedan(); } }; int main() { CarFactory* factory = new SUVFactory(); Car* car = factory->createCar(); car->drive(); delete car; delete factory; factory = new SedanFactory(); car = factory->createCar(); car->drive(); delete car; delete factory; return 0; }
Following is the output of the above code â
Driving an SUV Driving a Sedan
Simple Factory Pattern Implementation in C++
This is a simple way to implement the factory pattern also known as Static Factory Method. In this approach, we create a single class that contains a static method to create objects of different types based on the input parameters. Then, in the factory method, we use a switch statement or if-else statements to determine which type of object to create based on the input parameters.
Let's take an example of a shape factory. Here, we have a class Shape and different subclasses such as Circle and Square. We can create a static factory method in the ShapeFactory class to create objects of these subclasses based on the input parameters.
Example of Simple Factory Pattern in C++
Following is the code implementation of Simple Factory Pattern in C++
#include <iostream> #include <string> class Shape { public: virtual void draw() = 0; virtual ~Shape() {} }; class Circle : public Shape { public: void draw() { std::cout << "Drawing a Circle" << std::endl; } }; class Square : public Shape { public: void draw() { std::cout << "Drawing a Square" << std::endl; } }; class ShapeFactory { public: static Shape* createShape(const std::string& type) { if (type == "Circle") { return new Circle(); } else if (type == "Square") { return new Square(); } return nullptr; } }; class Client { public: void drawShape(const std::string& type) { Shape* shape = ShapeFactory::createShape(type); if (shape) { shape->draw(); delete shape; } else { std::cout << "Invalid shape type" << std::endl; } } }; int main() { Client client; client.drawShape("Circle"); client.drawShape("Square"); client.drawShape("Triangle"); return 0; }
Following is the output of the above code â
Drawing a Circle Drawing a Square Invalid shape type
Registry-based Factory Pattern Implementation in C++
This is a more advanced way to implement the factory pattern. In this approach, we create a registry of factory methods that can be used to create objects of different types. The registry is typically implemented as a map or dictionary that maps a string or an enum value to a factory method. This allows us to easily add new types of objects without modifying the existing code.
In the previous approaches, we have used block of if-else or used small factory classes for each type. But in this approach, we can centralize the creation logic in a single registry class.
Think of it as a map where â
- The key is the type of thing we want (like "Cat" or "Dog").
- The value is a function that knows how to make that thing we want.
It is like a notebook where you write down how to make different things. When you want to make something, you look it up in your notebook and follow the instructions. And when you want to make something new, you just add a new entry to your notebook without changing the existing ones.
This way, we can easily extend the factory to create new types of objects without modifying the existing code.
Example of Registry-based Factory Pattern in C++
Following is the code implementation of Registry-based Factory Pattern in C++.
#include <iostream> #include <string> #include <map> #include <functional> class Shape { public: virtual void draw() = 0; }; class Circle : public Shape { public: void draw() { std::cout << "Drawing a Circle" << std::endl; } }; class Square : public Shape { public: void draw() { std::cout << "Drawing a Square" << std::endl; } }; class ShapeFactory { public: using ShapeCreator = std::function<Shape*()>; static Shape* createShape(const std::string& type) { auto it = registry().find(type); if (it != registry().end()) { return it->second(); } return nullptr; } static void registerShape(const std::string& type, ShapeCreator creator) { registry()[type] = creator; } private: static std::map<std::string, ShapeCreator>& registry() { static std::map<std::string, ShapeCreator> instance; return instance; } }; class Client { public: void drawShape(const std::string& type) { Shape* shape = ShapeFactory::createShape(type); if (shape) { shape->draw(); delete shape; } else { std::cout << "Invalid shape type" << std::endl; } } }; int main() { ShapeFactory::registerShape("Circle", []() { return new Circle(); }); ShapeFactory::registerShape("Square", []() { return new Square(); }); Client client; client.drawShape("Circle"); client.drawShape("Square"); client.drawShape("Triangle"); return 0; }
Following is the output of the above code.
Drawing a Circle Drawing a Square Invalid shape type
The Registry-based Factory Pattern has several important properties that make it very useful for beginners to understand.
- First, it provides extensibility, which means you can easily add new types of shapes to your program without having to change any of the code you already wrote. This is like being able to add new recipes to your cookbook without having to rewrite the existing ones.
- Second, it offers centralized control, meaning all the logic for creating different shapes is kept in one place (the factory), making it much easier to manage and find when you need to make changes. Think of it like having all your tools organized in one toolbox instead of scattered around your garage.
- Finally, it provides decoupling, which is a fancy way of saying that the parts of your code that use the shapes don't need to know exactly how those shapes are created - they just ask the factory for what they need, similar to how you order food at a restaurant without needing to know how the kitchen prepares it.
Pros and Cons of Factory Method Pattern
Following are some of the pros and cons of using the Factory Method Pattern.
Pros | Cons |
---|---|
Encapsulates object creation logic. | Can cause unnecessary complexity if not used properly. |
Code become easy to reuse and maintain. | Multiple factory classes can make the codebase complex. |
Supports the Open/Closed Principle that allows new types of objects to be added without modifying existing code. | Can make the code harder to understand for developers who does not know the pattern. |
Decouples the client code from the concrete classes. | It may affect performance due to the additional layer of abstraction. |
Real-World Applications of Factory Method Pattern
Following are some real-world applications of the Factory Method Pattern:
- GUI Frameworks â Many GUI frameworks use factory methods to create UI components like buttons, text fields, etc.
- Game Development â In game development, factory methods are used to create different types of game objects (e.g., enemies, power-ups) without specifying their concrete classes.
- Database Connections â Factory methods can be used to create database connection objects, and allows them to be used interchangeably for different types of databases.
Conclusion
The Factory Method is a powerful creational design pattern which provides a way to create an object without exposing the creation logic to the client. We can make our code easy to maintain and also we can reuse it in different parts of the application. But, it is important to use the Factory Method carefully, as it can add unnecessary complexity to the codebase, if not used correctly.