Factory Method for Designing Pattern in C++
In C++, the factory method is a type of conditional design pattern. The factory method is related to creating a new object in C++. With the help of a factory object, we can create a new object without affecting the creation logic of the client side. Here the Client uses the same technique for creating a new object every time.
Here in this factory method, there is a need for the use of a static member function. We use the static member function for the return and creation of the instances. Also, with the help of the factory method, the user can hide the class module's details.
Here we can say that the factory method is a type of core principle used to create a new object, and that object allows the Client to create the object in the library. These objects are created in such a way that they do not have tight coupling between them and maintain a hierarchy class in the library function.
What is the meaning of libraries and clients?
Here, the term library means it provides a third party by which the user can fetch some APIs, and the Client can call those public APIs to complete their tasks. We can take the example of different types of views in the android operating system.
Example:
#include <iostream>
using namespace std;
class Vehicle {
public:
virtual void printVehicle() = 0;
};
class TwoWheeler : public Vehicle {
public:
void printVehicle()
{
cout << "I am two wheeler Vehicle" << endl;
}
};
class FourWheeler : public Vehicle {
public:
void printVehicle()
{
cout << "I am four wheeler Vehicle" << endl;
}
};
class Client {
public:
Client(int type)
{
if (type == 1)
pVehicle = new TwoWheeler();
else if (type == 2)
pVehicle = new FourWheeler();
else
pVehicle = NULL;
}
~Client()
{
if (pVehicle) {
delete pVehicle;
pVehicle = NULL;
}
}
Vehicle* getVehicle() { return pVehicle; }
private:
Vehicle* pVehicle;
};
int main()
{
Client* pClient = new Client(1);
Vehicle* pVehicle = pClient->getVehicle();
pVehicle->printVehicle();
return 0;
}
Output:
What are the problems with theabove design?
As we have seen in the above example, the Client can create either four wheelers or a two-wheeler vehicle object. Here the library also introduces a new object name ThreeWheeler to support the three-wheeler vehicle. So the Client will go to end up with a new object if the condition ladder creates a new object for the three-wheeler vehicle. So these types of changes are made up on the library side. So the user needs to make the changes on the client side also. This is a very bad practice for the programmer.
How do we avoid the problem?
There is a technique by which we can avoid that problem. The solution is we have to create a static method. Let's undethand this by the below example.
Example 2
#include <iostream>
using namespace std;
enum VehicleType {
VT_TwoWheeler, VT_ThreeWheeler, VT_FourWheeler
};
// Library classes
class Vehicle {
public:
virtual void printVehicle() = 0;
static Vehicle* Create(VehicleType type);
virtual ~Vehicle(){}
};
class TwoWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am two wheeler Vehicle" << endl;
}
};
class ThreeWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am three wheeler Vehicle" << endl;
}
};
class FourWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am four wheeler Vehicle" << endl;
}
};
Vehicle* Vehicle::Create(VehicleType type) {
if (type == VT_TwoWheeler)
return new TwoWheeler();
else if (type == VT_ThreeWheeler)
return new ThreeWheeler();
else if (type == VT_FourWheeler)
return new FourWheeler();
else return NULL;
}
class Client {
public:
Client()
{
VehicleType type = VT_ThreeWheeler;
pVehicle = Vehicle::Create(type);
}
~Client() {
if (pVehicle) {
delete pVehicle;
pVehicle = NULL;
}
}
Vehicle* getVehicle() {
return pVehicle;
}
private:
Vehicle *pVehicle;
};
int main() {
Client *pClient = new Client();
Vehicle * pVehicle = pClient->getVehicle();
pVehicle->printVehicle();
delete pClient;
return 0;
}
Output:
In the above example, we have totally decoupled the selection of types for object creation from the Client. The library is now responsible for deciding which object type to create based on input. The Client just needs to make calls to the library's factory Create method and pass the type it wants without worrying about the actual implementation of the creation of objects.