Example comparison of simple factory and factory method patterns in C++ design pattern programming

  • 2020-05-09 19:00:12
  • OfStack

Example of a simple factory pattern
Title: the implementation of the calculator input 2 Numbers and operators, the results

Engineering structure:

(1) header files

COperationFactory.h (operator factory class)

(2) the source file

SimpleFactory.cpp (client application class, where the main function is)

(3) class

COperation. cpp (operator base class)
COperation.h
COperationAdd.h (addition operator subclass, inherited from COperation)
COperationDiv.h (subclass of division operator, inherited from COperation)
COperationMul.h (multiplication operator subclass, inherited from COperation)
COperationSub.h (subclass of subtraction operator, inherited from COperation)

============= ==   code implementation ============= =====

COperationFactory.h (operator factory class)


/************************************************************************/ 
/*  Operator factory class  */ 
/************************************************************************/ 
#ifndef _OPERATION_FACTORY_H_ 
#define _OPERATION_FACTORY_H_ 
 
#include "stdafx.h" 
#include "COperation.h" 
#include "COperationAdd.h" 
#include "COperationSub.h" 
#include "COperationMul.h" 
#include "COperationDiv.h" 
#include "COperationFactory.h" 
 
class COperationFactory 
{ 
public: 
  COperationFactory(){}; 
  ~COperationFactory(){}; 
 
  //  The corresponding operator class pointer is created according to the input parameters. Like a factory, create a user-specified operator class pointer  
  static COperation* NewOperation(const string& strOperate) 
  { 
    //  Enter the legitimacy judgment to prevent the latter strOperate[0] Cross-border visits occurred  
    if (strOperate.size() != 1) 
    { 
      return NULL; 
    } 
 
    COperation* pOperation = NULL; 
    switch (strOperate[0]) 
    { 
    case '+': 
      pOperation = new COperationAdd(); 
      break; 
    case '-': 
      pOperation = new COperationSub(); 
      break; 
    case '*': 
      pOperation = new COperationMul(); 
      break; 
    case '/': 
      pOperation = new COperationDiv(); 
      break; 
    default: 
      break; 
    } 
 
    return pOperation; 
  }; 
}; 
 
#endif _OPERATION_FACTORY_H_ 

 
COperation.cpp (operator base class)


#include "stdafx.h" 
#include "COperation.h" 
 
COperation::COperation() 
  : _dNumA(0) 
  , _dNumB(0) 
{ 
 
} 

COperation.h


/************************************************************************/ 
/*  Operator base class  */ 
/************************************************************************/ 
 
#ifndef _COPERATION_H_ 
#define _COPERATION_H_ 
 
class COperation 
{ 
public: 
  COperation(); 
  ~COperation(){}; 
     
  //  Sets the number to be evaluated  
  void SetNumA(double dNumA) 
  { 
    _dNumA = dNumA; 
  }; 
   
  //  Gets the number to be evaluated  
  double GetNumA() 
  { 
    return _dNumA; 
  }; 
 
  //  Set operand  
  void SetNumB(double dNumB) 
  { 
    _dNumB = dNumB; 
  }; 
 
  //  Fetch operand  
  double GetNumB() 
  { 
    return _dNumB; 
  }; 
 
  //  Calculate the result and implement the result of the respective operation method in the subclass  
  virtual double Result() 
  { 
    double dResult = 0; 
    return dResult; 
  } 
 
private: 
  double _dNumA; 
  double _dNumB; 
}; 
 
#endif _COPERATION_H_ 

COperationAdd.h (addition operator subclass, inherited from COperation)


/************************************************************************/ 
/*  The addition operator subclass, which is inherited from the operator base class  */ 
/************************************************************************/ 
#ifndef _COPERATION_ADD_H_ 
#define _COPERATION_ADD_H_ 
#include "COperation.h" 
 
 class COperationAdd : public COperation 
 { 
 public: 
   COperationAdd(){}; 
   ~COperationAdd(){}; 
 
   double Result() 
   {      
     return (GetNumA() + GetNumB()); 
   };   
 }; 
 
#endif _COPERATION_ADD_H_ 

COperationDiv.h (subclass of division operator, inherited from COperation)


/************************************************************************/ 
/*  Subclass of the division operator, which is inherited from the operator base class  */ 
/************************************************************************/ 
#ifndef _COPERATION_DIV_H_ 
#define _COPERATION_DIV_H_ 
#include "COperation.h" 
 
class COperationDiv : public COperation 
{ 
public: 
  COperationDiv(){}; 
  ~COperationDiv(){}; 
 
  double Result() 
  { 
    double dResult = 0; 
    if (0 != GetNumB()) 
    { 
      dResult = (GetNumA() / GetNumB()); 
    } 
    else 
    { 
      cout << "error: divisor is "; 
    } 
    return dResult; 
  };   
}; 
 
#endif _COPERATION_DIV_H_ 

COperationMul.h (multiplication operator subclass, inherited from COperation)


/************************************************************************/ 
/*  A subclass of the multiplication operator that is inherited from the operator base class  */ 
/************************************************************************/ 
#ifndef _COPERATION_MUL_H_ 
#define _COPERATION_MUL_H_ 
#include "COperation.h" 
 
class COperationMul : public COperation 
{ 
public: 
  COperationMul(){}; 
  ~COperationMul(){}; 
 
  double Result() 
  {     
    return (GetNumA() * GetNumB()); 
  };   
}; 
 
#endif _COPERATION_MUL_H_ 

COperationSub.h (subclass of subtractive operator, inherited from COperation)


/************************************************************************/ 
/*  Subclasses of subtractive operators, which are inherited from the operator base class  */ 
/************************************************************************/ 
#ifndef _COPERATION_SUB_H_ 
#define _COPERATION_SUB_H_ 
#include "COperation.h" 
 
class COperationSub : public COperation 
{ 
public: 
  COperationSub(){}; 
  ~COperationSub(){}; 
 
  double Result() 
  {     
    return (GetNumA() - GetNumB()); 
  };   
}; 
 
#endif _COPERATION_SUB_H_ 

SimpleFactory.cpp (client application class, where the main function is)


// SimpleFactory.cpp :  Define the entry point for the console application.  
// 
 
#include "stdafx.h" 
#include "COperationFactory.h" 
 
int _tmain(int argc, _TCHAR* argv[]) 
{   
  //  Create an addition operation through an operator factory  
  COperation* OperAdd = COperationFactory::NewOperation("+"); 
  if (NULL != OperAdd) 
  { 
    OperAdd->SetNumA(168); //  Set the addend  
    OperAdd->SetNumB(105); //  Set the addend      
    cout << "168 + 105 = " << (OperAdd->Result()) << endl; 
  } 
 
  //  Creates a subtraction operation through an operator factory  
  COperation* OperSub = COperationFactory::NewOperation("-"); 
  if (NULL != OperSub) 
  { 
    OperSub->SetNumA(168); //  Set the minuend  
    OperSub->SetNumB(105); //  Set the reduction      
    cout << "168 - 105 = " << (OperSub->Result()) << endl; 
  } 
 
  //  Create the multiplication operation through the operator factory  
  COperation* OperMul = COperationFactory::NewOperation("*"); 
  if (NULL != OperMul) 
  { 
    OperMul->SetNumA(168); //  Set the multiplicand  
    OperMul->SetNumB(105); //  Set the multiplier      
    cout << "168 * 105 = " << (OperMul->Result()) << endl; 
  } 
 
  //  Creates a division operation through an operator factory  
  COperation* OperDiv = COperationFactory::NewOperation("/"); 
  if (NULL != OperDiv) 
  { 
    OperDiv->SetNumA(168); //  Set the dividend  
    OperDiv->SetNumB(105); //  Set the divisor      
    cout << "168 / 105 = " << (OperDiv->Result()) << endl; 
     
    OperDiv->SetNumB(0);  //  Change the divisor  
    cout << (OperDiv->Result()) << endl; 
  } 
 
  //  Prevents the console process from ending to facilitate viewing the results  
  int nEnd = 0; 
  cin >> nEnd; 
 
  return 0; 
} 

Abstract factory pattern instances

Engineering structure:

(1) abstract products

IFruit.h

(2) abstract factory class

IFruitGardener.h

(3) specific products

CApple.h

CGrape.h

CStrawberry.h

(4) specific factories

CAppleGardener.h

CGrapeGardener.h

CStrawberryGardener.h

(5) client

FactoryMethodApplication.cpp

(1) abstract products

IFruit.h


/************************************************************************/ 
/*  Abstract fruits (abstract Product) */ 
/************************************************************************/ 
#ifndef _IFRUIT_H_ 
#define _IFRUIT_H_ 
 
#include <string> 
#include <iostream> 
using namespace std; 
 
class IFruit 
{ 
public: 
  virtual void grow() = 0; 
  virtual void harvest() = 0; 
  virtual void plant() = 0; 
}; 
 
#endif _IFRUIT_H_ 

 

(2) abstract factory class

IFruitGardener.h


/************************************************************************/ 
/*  Abstract fruit gardeners (abstract Factory) */ 
/************************************************************************/ 
#ifndef _IFRUIT_GARDENER_H_ 
#define _IFRUIT_GARDENER_H_ 
 
#include "IFruit.h" 
 
class IFruitGardener 
{ 
public: 
  virtual IFruit* Factory() = 0; 
}; 
 
#endif _IFRUIT_GARDENER_H_ 

 

(3) specific products

CApple.h


#include "stdafx.h" 
#include "COperation.h" 
 
COperation::COperation() 
  : _dNumA(0) 
  , _dNumB(0) 
{ 
 
} 

0

 

CGrape.h


#include "stdafx.h" 
#include "COperation.h" 
 
COperation::COperation() 
  : _dNumA(0) 
  , _dNumB(0) 
{ 
 
} 

1

CStrawberry.h


#include "stdafx.h" 
#include "COperation.h" 
 
COperation::COperation() 
  : _dNumA(0) 
  , _dNumB(0) 
{ 
 
} 

2

 

(4) specific factories

CAppleGardener.h


/************************************************************************/ 
/*  Specific apple gardener category (Concrete Factory) */ 
/************************************************************************/ 
#ifndef _APPLE_GARDENER_H_ 
#define _APPLE_GARDENER_H_ 
 
#include "IFruitGardener.h" 
#include "CApple.h" 
 
class CAppleGardener : public IFruitGardener 
{ 
public: 
  CAppleGardener():m_pApple(NULL){}; 
 
  IFruit* Factory() 
  { 
    if (NULL == m_pApple) 
    { 
      m_pApple = new CApple(); 
    } 
 
    return m_pApple; 
  }; 
 
private: 
  CApple* m_pApple; 
}; 
 
#endif _APPLE_GARDENER_H_ 

CGrapeGardener.h


#include "stdafx.h" 
#include "COperation.h" 
 
COperation::COperation() 
  : _dNumA(0) 
  , _dNumB(0) 
{ 
 
} 

4

CStrawberryGardener.h


#include "stdafx.h" 
#include "COperation.h" 
 
COperation::COperation() 
  : _dNumA(0) 
  , _dNumB(0) 
{ 
 
} 

5

 

(5) client

FactoryMethodApplication.cpp


#include "stdafx.h" 
#include "COperation.h" 
 
COperation::COperation() 
  : _dNumA(0) 
  , _dNumB(0) 
{ 
 
} 

6

conclusion

First of all, both the simple factory pattern and the factory method pattern extract the invariable places and encapsulate the easily changed ones. In order to achieve a large degree of reuse, and adapt to user changes, as well as the expansion of the project.

1. Simple factory model

1. Understand

Also known as the static factory pattern, it defines a class that is responsible for creating instances of other classes, which usually have the same parent class. The factory class dynamically determines which instances of the product class should be created based on the parameters passed in. It contains the necessary judgment logic to determine which concrete class of objects should be worn based on the given information. The simple factory model can be understood as a father leaving a sum of money for his son to go to school, buy a house or a car, and then letting the son choose which one to use.

2. The advantages

The factory class contains the necessary logic to determine when to create an instance of which class, and the client can avoid creating objects directly. In this way, the division of responsibilities can be realized, the coupling can be reduced, and the specific responsibilities and powers can be defined, which is conducive to the optimization of the whole system.

3. The shortcomings

When the product has a relatively complex multi-layer structure, its factory class is only 1, at this time, it will become its biggest disadvantage. Because the factory class is the core of the whole organization, it gathers the creation logic of all products. Once the factory cannot work normally, the whole system will be affected and the scalability will be poor. When there are new requirements, the factory logic will have to be modified, which will lead to the complexity of the factory logic and violate the open-close principle. At the same time, the static factory method is not conducive to the formation of a hierarchical structure based on inheritance.

2. Factory method mode

1. Understand

It is a fine-grained design pattern because the representation of the pattern is an abstract method. The factory method pattern defines an interface for creating objects and lets subclasses decide which class to instantiate. In other words, the interface is added between the factory and the product. The factory is no longer responsible for the implementation of the product. There is an excuse to return different class instances for different conditions, and then the concrete class instances will be implemented. The factory method is a derivative of the simple factory, which improves many of the disadvantages of the simple factory, follows the open-close principle, and achieves scalability, which can be used in more complex product results. The factory method can be understood as the same father left his son a sum of money, and then directly let the son to control, how to spend the father 1 law does not care.

2. The advantages

The factory method model overcomes many of the disadvantages of simple factories. It only completes the single task per specific factory, and follows the open-close principle. The code is concise and has good scalability.

3. The shortcomings

If a product class needs to be modified, the corresponding factory class also needs to be modified. Once there are more than one product class that needs to be modified, the problem of matching will appear, and it will become quite complicated to modify the factory class. So the factory method pattern, while good for scaling, is bad for maintenance.

With all of this in mind, we can see which pattern is most beneficial for programming in different situations. The simple factory pattern can be used when there are few objects to create and the customer only knows the parameters passed into the factory and does not care how to create the objects. The factory method pattern is used when a class delegates responsibility for creating an object to one of several help subclasses.


Related articles: