Design Patterns represent solutions to problems what arise when developing software within a particular context.
Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.
Basically, there are three categories:
Creational Patterns: deal with initializing and configuring classes and objects
Structural Patterns: deal with decoupling the interface and implementation of classes and objects
Behavioral Patterns: deal with dynamic interactions among societies of classes and objects
creates objects without exposing the instantiation logic to the client.
refers to the newly created object through a common interface
The implementation is really simple
The client needs a product, but instead of creating it directly using the new operator, it asks the factory object for a new product, providing the information about the type of object it needs.
The factory instantiates a new concrete product and then returns to the client the newly created product(casted to abstract product class).
The client uses the products as abstract products without being aware about their concrete implementation.
Probably the factory pattern is one of the most used patterns.
For example a graphical application works with shapes. In our implementation the drawing framework is the client and the shapes are the products. All the shapes are derived from an abstract shape class (or interface). The Shape class defines the draw and move operations which must be implemented by the concrete shapes. Let's assume a command is selected from the menu to create a new Circle. The framework receives the shape type as a string parameter, it asks the factory to create a new shape sending the parameter received from menu. The factory creates a new circle and returns it to the framework, casted to an abstract shape. Then the framework uses the object as casted to the abstract class without being aware of the concrete object type.
The advantage is obvious: New shapes can be added without changing a single line of code in the framework(the client code that uses the shapes from the factory). As it is shown in the next sections, there are certain factory implementations that allow adding new products without even modifying the factory class.
Look at the following example in C++:
Abstract Interface Class:
struct IAutoMobile
{
virtual bool Register(const std::string& RegistrationNumber) = 0;
virtual VehicleType GetType() = 0;
virtual VehicleColor GetColor() = 0;
};
Specific Implementation Class(es)
class CCar:public IAutoMobile
{
public:
CCar(const VehicleSpecification& VSpecs);
virtual bool Register(const std::string& RegistrationNumber);
virtual VehicleType GetType(){ return m_VehicleType;}
virtual VehicleColor GetColor(){return m_VehicleColor;}
virtual ~CCar();
private:
VehicleType m_VehicleType;
VehicleColor m_VehicleColor;
bool m_fRegistered;
std::string m_RegistrationNumber;
};
CCar::CCar(const VehicleSpecification& VSpecs)
{
m_VehicleType = VehicleType::CAR;
m_VehicleColor = VSpecs.Color;
m_fRegistered = false;
}
bool CCar::Register(const std::string& RegistrationNumber)
{
m_RegistrationNumber = RegistrationNumber;
m_fRegistered = true;
return true;
}
Factory Class Declaration
class CVehicleFactory
{
public:
static IAutoMobile* GetVehicle(const VehicleSpecification& VSpecs);
private:
//Lock-Down un-wanted stuff/Don't let this class to be initiated
CVehicleFactory();
CVehicleFactory(CVehicleFactory& CloneObj);
CVehicleFactory& operator=(CVehicleFactory& CloneObj);
};
IAutoMobile* CVehicleFactory::GetVehicle(const VehicleSpecification& VSpecs)
{
IAutoMobile *pAutoMobile = nullptr;
if(VSpecs.Type == VehicleType::CAR ){
pAutoMobile = new CCar(VSpecs);