Introduction to the factory model

Let’s start with an introduction to the factory model

This type of design pattern is the creation pattern, which provides the best way to create objects. In factory mode, we create objects without exposing the creation logic to the client, and by using a common interface to point to the newly created objects.

To put it simply, using the C++ polymorphism feature, a factory class creates a corresponding subclass (derived class) object for a class that has an inheritance relationship. In the case of complex projects, it is easy to create subclass objects.

The implementation of factory pattern can be divided into simple factory pattern, factory method pattern and abstract factory pattern, and each implementation has advantages and disadvantages.

Recently fried shoes fried very fire, so in the form of shoe factory, one by one analysis for each implementation of the analysis.


Simple Factory model

Specific situations:
  • Shoe factories can designate Nike, Adidas and Li Ning shoes. Which shoes fry hot, the boss produces which, see the situation production.
UML diagrams:

Simple factory modelStructural components:
  1. The factory class(ShoesFactory) : The core class of the factory pattern defines an interface for creating specified concrete instance objects.
  2. Abstract product class(Shoes) : is an inherited parent or implemented interface of a concrete product class.
  3. Specific product category(NiKeShoes\AdidasShoes\LiNingShoes) : The object created by the factory class is this concrete product instance.
Simple factory modelThe characteristics of:
  • The factory class encapsulates the functions that create concrete product objects.
Simple factory modeldefects:
  • The scalability is very poor. When adding new products, we need to modify the factory class.
Simple factory modelcode:
  • ShoesIs the abstract class (base class) of shoes, and the interface function isShow(), used to display shoe ads.
  • NiKeShoes,AdidasShoes,LiNingShoesFor the specific shoe category, they are Nike, Adidas and Li Ning shoes brand shoes, they are inherited fromShoesAn abstract class.
// Shoe abstract class
class Shoes
{
public:
    virtual ~Shoes() {}
    virtual void Show(a) = 0;
};

// Nike shoes
class NiKeShoes : public Shoes
{
public:
    void Show(a)
    {
        std: :cout << "I'm a Nike sneaker, my slogan: Just do it." << std: :endl; }};Adidas shoes
class AdidasShoes : public Shoes
{
public:
    void Show(a)
    {
        std: :cout << "I'm Adidas, my slogan :Impossible is nothing." << std: :endl; }};// Li Ning shoes
class LiNingShoes : public Shoes
{
public:
    void Show(a)
    {
        std: :cout << "I am Li Ning sneakers, my slogan: Everything is possible" << std: :endl; }};Copy the code
  • ShoesFactoryIs the factory class, in which the corresponding shoe product object is created according to the shoe typeCreateShoes(SHOES_TYPE type)Function.
enum SHOES_TYPE
{
    NIKE,
    LINING,
    ADIDAS
};

/ / total shoe factory
class ShoesFactory
{
public:
    // Create a shoe object based on the shoe type
    Shoes *CreateShoes(SHOES_TYPE type)
    {
        switch (type)
        {
        case NIKE:
            return new NiKeShoes();
            break;
        case LINING:
            return new LiNingShoes();
            break;
        case ADIDAS:
            return new AdidasShoes();
            break;
        default:
            return NULL;
            break; }}};Copy the code
  • mainFunction, first constructs the factory object, then creates the specific shoe product object of the specified type, the creation of the specific shoe product object can directly print the advertisement. Because we’re using thetanewThe way an object is created is used up to pass throughdeleteRelease resources Resources oh!
int main(a)
{
    // Construct the factory object
    ShoesFactory shoesFactory;

    // Create an Adidas shoe object from the shoe factory object
    Shoes *pNikeShoes = shoesFactory.CreateShoes(NIKE);
    if(pNikeShoes ! =NULL)
    {
        // Shouted the Nike shoe AD
        pNikeShoes->Show();

        // Release resources
        delete pNikeShoes;
        pNikeShoes = NULL;
    }

    // Create an Adidas shoe object from the shoe factory object
    Shoes *pLiNingShoes = shoesFactory.CreateShoes(LINING);
    if(pLiNingShoes ! =NULL)
    {
        // Li Ning sneaker advertisement shouted
        pLiNingShoes->Show();

        // Release resources
        delete pLiNingShoes;
        pLiNingShoes = NULL;
    }

    // Create an Adidas shoe object from the shoe factory object
    Shoes *pAdidasShoes = shoesFactory.CreateShoes(ADIDAS);
    if(pAdidasShoes ! =NULL)
    {
        // Adidas shoe advertisement shouted
        pAdidasShoes->Show();

        // Release resources
        delete pAdidasShoes;
        pAdidasShoes = NULL;
    }

    return 0;
}
Copy the code
  • Output result:
[root@lincoding factory]#./simpleFactory I am Nike shoes, my slogan: Just do it I am Adidas shoes, my slogan :Impossible is nothing I am Li Ning shoes, my slogan: Everything is possibleCopy the code

Factory method pattern

Specific situation:
  • Now all kinds of shoes copy is very hot, so in order to mass produce each type of shoes, it is necessary to open independent production lines for different brands of shoes, so each production line can only produce shoes of the same type of brand.
UML diagrams:

Factory method patternStructural components:
  1. Abstract Factory classFactory (ShoesFactory) : The core class of the factory method pattern, which provides an interface to create concrete products, implemented by concrete factory classes.
  2. Specific Factory(NiKeProducer\AdidasProducer\LiNingProducer) : Inherits from abstract factories to implement the way to create objects corresponding to concrete products.
  3. Abstract product class(Shoes) : It is the parent class (base class) from which the concrete product inherits.
  4. Specific product category(NiKeShoes\AdidasShoes\LiNingShoes) : Objects created by specific factories are such.
Factory method patternThe characteristics of:
  • The factory method pattern abstracts out factory classes, providing interfaces to create concrete products that subclasses implement.
  • The factory method pattern is used not only to encapsulate the creation of concrete product objects, but to put the creation of concrete product objects into concrete factory class implementation.
Factory method patterndefects:
  • Every time you add a product, you need to add a specific factory class for that product. The factory method pattern requires more class definitions than the simple factory pattern.
  • There is only one product per production line.
Code for the factory method pattern:
  • ShoesFactoryAbstract factory class, which provides pure virtual functions to create concrete shoe products.
  • NiKeProducer,AdidasProducer,LiNingProducerConcrete factory class, inherit the continuous factory class, to achieve the creation of the corresponding specific shoe product object.
/ / total shoe factory
class ShoesFactory
{
public:
    virtual Shoes *CreateShoes(a) = 0;
    virtual ~ShoesFactory() {}
};

// Nike producer/production chain
class NiKeProducer : public ShoesFactory
{
public:
    Shoes *CreateShoes(a)
    {
        return newNiKeShoes(); }};// Adidas producer/production chain
class AdidasProducer : public ShoesFactory
{
public:
    Shoes *CreateShoes(a)
    {
        return newAdidasShoes(); }};// Li Ning producer/production chain
class LiNingProducer : public ShoesFactory
{
public:
    Shoes *CreateShoes(a)
    {
        return newLiNingShoes(); }};Copy the code
  • mainThe function constructs each type of production line for each type of shoe, and then produces the corresponding shoe from each production line. Note that specific factory objects and specific product objects need to be passed when used updeleteRelease resources.
int main(a)
{
    / / = = = = = = = = = = = = = = = = the production process of Nike = = = = = = = = = = = = = = = = = = = = / /
    // The shoe factory opened a Nike production line
    ShoesFactory *niKeProducer = new NiKeProducer();
    // The Nike production line produces sneakers
    Shoes *nikeShoes = niKeProducer->CreateShoes();
    // Shouted the Nike shoe AD
    nikeShoes->Show();
    // Release resources
    delete nikeShoes;
    delete niKeProducer;

    / / = = = = = = = = = = = = = = = = production process of adidas = = = = = = = = = = = = = = = = = = = = / /
    // Shoe factory opens adidas producer
    ShoesFactory *adidasProducer = new AdidasProducer();
    // Adidas production line produces sneakers
    Shoes *adidasShoes = adidasProducer->CreateShoes();
    // Adidas sneakers shouted
    adidasShoes->Show();
    // Release resources
    delete adidasShoes;
    delete adidasProducer;

    return 0;
}
Copy the code
  • Output result:
[root@lincoding Factory]#./methodFactory I am Nike, my slogan: Just do it I am Adidas, my slogan :Impossible is nothingCopy the code

Abstract Factory pattern

Specific situation:
  • In order to expand its business, the shoe company has expanded its production of sports brands as well as shoes.
UML diagrams:

The structural composition of the abstract factory pattern (as in the factory Method pattern) :
  1. Abstract Factory classFactory (ShoesFactory) : The core class of the factory method pattern, which provides an interface to create concrete products, implemented by concrete factory classes.
  2. Specific Factory(NiKeProducer) : Inherits from abstract factories to implement the way to create objects corresponding to concrete products.
  3. Abstract product class(Shoes\Clothe) : It is the parent class (base class) from which the concrete product inherits.
  4. Specific product category(NiKeShoes\NiKeClothe) : Objects created by specific factories are such.
Abstract Factory pattern features:
  • Provides an interface to create product objects in multiple product families. For example, Nike factory can create Nike shoes, clothing products, pants products and so on.
Pitfalls of the Abstract Factory pattern:
  • As with the factory method pattern, when you add a product, you need to add a specific factory class for the corresponding product.
Abstract factory code:
  • ClotheandShoesAre the abstract product categories of clothing and shoes respectively.
  • NiKeClotheandNiKeShoes, are specific product categories of Nike clothing and Nike clothing respectively.
// Basic clothes
class Clothe
{
public:
    virtual void Show(a) = 0;
    virtual ~Clothe() {}
};

// Nike clothes
class NiKeClothe : public Clothe
{
public:
    void Show(a)
    {
        std: :cout << "I'm Nike. I know fashion!" << std: :endl; }};// Base shoes
class Shoes
{
public:
    virtual void Show(a) = 0;
    virtual ~Shoes() {}
};

// Nike shoes
class NiKeShoes : public Shoes
{
public:
    void Show(a)
    {
        std: :cout << "I'm a Nike shoe to make you cool!" << std: :endl; }};Copy the code
  • FactoryProvides for abstract factory to create shoesCreateShoes()And clothing productsCreateClothe()Object interface.
  • NiKeProducerFor the specific factory, the way to create Nike shoes and Nike clothing was realized.
/ / factory
class Factory
{
public:
    virtual Shoes *CreateShoes(a) = 0;
	virtual Clothe *CreateClothe(a) = 0;
    virtual ~Factory() {}
};

// Nike producer/production chain
class NiKeProducer : public Factory
{
public:
    Shoes *CreateShoes(a)
    {
        return new NiKeShoes();
    }
	
	Clothe *CreateClothe(a)
    {
        return newNiKeClothe(); }};Copy the code
  • mainFunction to construct the Nike factory object, which then creates the Nike product family clothing and shoe objects. Similarly, when objects are no longer in use, resources need to be released manually.
int main(a)
{
    / / = = = = = = = = = = = = = = = = the production process of Nike = = = = = = = = = = = = = = = = = = = = / /
    // The shoe factory opened a Nike production line
    Factory *niKeProducer = new NiKeProducer();
    
	// The Nike production line produces sneakers
    Shoes *nikeShoes = niKeProducer->CreateShoes();
	// The Nike line produces the clothes
    Clothe *nikeClothe = niKeProducer->CreateClothe();
    
	// Shouted the Nike shoe AD
    nikeShoes->Show();
	"// Nike clothing ads shouted
    nikeClothe->Show();
	
    // Release resources
    delete nikeShoes;
	delete nikeClothe;
    delete niKeProducer;


    return 0;
}
Copy the code
  • Output result:
[root@lincoding factory]#./abstractFactory I'm Nike sneakers, make you cool! I'm Nike. I know fashion!Copy the code

conclusion

The above three factory models all have certain defects when adding new products.

  • Simple factory mode, which requires modification of the factory class, violates the on/off rule.
  • Both the factory mode pattern and the abstract factory pattern require the addition of a specific factory class corresponding to the product, which increases the amount of code to write.

So what’s a good way to add a product without either modifying the factory class or adding a specific factory class?

In the actual project, the author saw a factory class with very strong encapsulation. When expanding new products, there is no need to modify the factory class, and no need to add specific factory classes. The details can be skipped to C++ simple factory mode (advanced) for reading.