Design pattern | factory pattern (simple factory, factory method, abstract factory)

Posted by molave on Thu, 17 Feb 2022 13:08:03 +0100

catalogue

Simple factory

Factory method

Abstract factory

Learning factory mode requires relevant inheritance and polymorphism knowledge such as C + + virtual function and pure virtual function

Simple factory

In simple factory mode, different instances can be returned according to different parameters.. The simple factory pattern specifically defines a class to be responsible for creating instances of other classes. The created instances have a common parent class. In other words, the creation of objects is encapsulated in an interface function, and the created objects are returned by passing in different identifiers. The customer does not need to be responsible for the new object and understand the detailed process of object creation. Disadvantages: the interface function for creating object instances is not closed and cannot be closed for modification

Simple factory role:

Factory role factory: the core of the simple factory pattern, which is responsible for implementing the internal logic of creating all instances. Factory's method of creating a product class can be directly called by the outside world to create the product object required by the outside world

Description of the common role of the factory (the parent class of the factory is responsible for the creation of all instances of the common Product): product

Concrete product: it is the creation target of simple factory mode. All created objects are instances of a specific product

 

For example: Xiaomi company wants to produce Xiaomi 18. Xiaomi company first develops various modules of mobile phones, draws drawings, and then gives them to Foxconn or BYD to produce mobile phones.

Role play

Abstract product role: Xiaomi mobile phone

Specific product role: Xiaomi 18

Factory role: Foxconn / BYD

UML class view

Code implementation

enum CarType
{
    FERRARI,
    MAYBACH,
    MASERATY,
};
//Defining Abstract cars
class Car
{
public:
    Car(){}
    virtual void show() = 0;
};

//Define specific car brands
class Ferrari : public Car
{
public:
    Ferrari() {}
    void show()
    {
        cout << "create Ferrari" << endl;
    }
};

class Maybach : public Car
{
public:
    Maybach(){}
    void show()
    {
        cout << "create Maybach" << endl;
    }
};

class Maserati : public Car
{
public:
    Maserati(){}
    void show()
    {
        cout << "create Maserati" << endl;
    }
};

//Define factory roles
class Factory
{
public:
    Car *create(CarType car)
    {
        switch (car)
        {
        case FERRARI:
            return new Ferrari();
            break;
        case MAYBACH:
            return new Maybach();
            break;
        case MASERATY:
            return new Maserati();
            break;
        }
        return nullptr;
    }
};

int main()
{
    unique_ptr<Factory>factory(new Factory());
    unique_ptr<Car>p1(factory->create(FERRARI));
    unique_ptr<Car>p2(factory->create(MAYBACH));
    unique_ptr<Car>p3(factory->create(MASERATY));
    p1->show();
    p2->show();
    p3->show();

    return 0;
}

SimpleFactory simple Factory solves some problems, but it also has obvious problems, that is, it encapsulates the creation of all objects in the create function of a Factory class, and selects and generates different objects according to the passed in parameters. Obviously, the create function cannot follow the "open close" principle, that is, it is closed to the modification of the original code and open to function expansion, With the addition of new objects or the deletion of original objects, the code of this function will be modified, and the original function may be affected. Therefore, this design is not perfect.
 

Factory method

The Factory base class provides a pure virtual function (creating products) and defines derived classes (factories of specific products) to create corresponding products. Different products can be created in different factories, and existing factories and product modifications can be closed.

Factory method pattern role

● Abstract Factory role: the core of the method pattern, independent of the application. The factory class of any object created in the schema must implement this interface.

● specific factory role: This is a specific factory class that implements the abstract factory interface. It contains logic closely related to the application and is called by the application to create a product object.

● abstract product role: the object type created by the factory method pattern, that is, the common parent class or jointly owned interface of the product object.

● specific product role: This implements the interface defined by the abstract product color. A specific product is created in a specific factory, and they often correspond to each other one by one.

For example, when Xiaomi wanted to build Xiaomi 18, Lei always felt that the quality of Foxconn OEM was not good, so he invested and built a Xiaomi mobile phone manufacturing factory to produce Xiaomi mobile phones. Let these OEM factories see how to build mobile phones. Xiaomi 18 was built by Xiaomi's own factory

cosplay:

Abstract factory role: mobile factory

Specific factory role: Xiaomi mobile phone manufacturer

Abstract product role: Xiaomi mobile phone

Specific product role: Xiaomi 18

UML class view

Code implementation

//Defining Abstract cars
class Car
{
public:
    Car() {}
    virtual void show() = 0;
};

//Define specific car brands
class Ferrari : public Car
{
public:
    Ferrari() {}
    void show()
    {
        cout << "create Ferrari" << endl;
    }
};

class Maybach : public Car
{
public:
    Maybach() {}
    void show()
    {
        cout << "create Maybach" << endl;
    }
};

class Maserati : public Car
{
public:
    Maserati() {}
    void show()
    {
        cout << "create Maserati" << endl;
    }
};

class Factory
{
public:
    virtual Car *create() = 0;
};

class FerrariFactory : public Factory
{
public:
    Car *create()
    {
        return new Ferrari();
    }
};

class MaseratiFactory : public Factory
{
    Car *create()
    {
        return new Maserati();
    }
};

class MaybachFactory : public Factory
{
    Car *create()
    {
        return new Maybach();
    }
};

int main()
{

    //Call is an interface that doesn't care about concrete classes, but only about abstract classes
    //Instantiate three factories
    unique_ptr<Factory> f1(new FerrariFactory);
    unique_ptr<Factory> f2(new MaybachFactory);
    unique_ptr<Factory> f3(new MaseratiFactory);

    //Instantiate three cars
    unique_ptr<Car> p1(f1->create());
    unique_ptr<Car> p2(f2->create());
    unique_ptr<Car> p3(f3->create());

    p1->show();
    p2->show();
    p3->show();

    return 0;
}

If you carefully understand the above factory method mode, you will find a problem that each instance factory is responsible for producing one instance product, that is, one product corresponds to one factory and one factory corresponds to one product. Then Xiaomi not only produces mobile phones, but also produces relevant Xiaomi product clusters such as headphones, smart bracelets, smart sockets and so on, It is impossible to create a factory class for each product. In that case, there are too many classes in the code, which is difficult to maintain and does not conform to the actual situation.

In fact, in the factories of Xiaomi or Huawei, the associated product clusters are created in one factory; In addition to producing automobiles, BMW or Audi automobile manufacturing plants may also produce tires or other automobile accessories on the production line.

Therefore, for the design of entity relationships including product clusters, you need to use Abstract Factory. You can also regard the above factory method as an Abstract Factory that produces only one product, which is essentially the same.
 

Abstract factory

Abstract factory role

Abstract factory: it provides an interface for creating products. It contains multiple methods for creating products, newProduct(), which can create multiple products of different levels.

Concrete factory: it mainly realizes multiple abstract methods in the abstract factory to complete the creation of specific products.

Abstract product: Zhao defines the product specification and describes the main characteristics and functions of the product. The abstract factory model has multiple Abstract products.

Concrete product: it implements the interface defined by the abstract product color and is created by the concrete factory. It has a many to one relationship with the concrete factory.

For example: Lei always felt that his Xiaomi mobile phone manufacturer could not make Xiaomi mobile phones alone. Lei always decided to bet all the achievements and honors accumulated in his life to build cars. In this way, Xiaomi's factory not only makes mobile phones, but also cars. Xiaomi factory business: making cars, mobile phones, bracelets, smart speakers Such businesses are made in their own factories.

cosplay

Abstract factory role: mobile factory

Specific factory role: Xiaomi mobile phone manufacturer

Abstract product roles: Xiaomi mobile phone, car, smart speaker, Xiaomi Bracelet...

Specific product roles: Xiaomi 18, Xiaomi car, Xiaomi smart speaker, Xiaomi Bracelet

UML class view

Code implementation

/Define abstract car products
class Car
{
public:
    virtual void show() = 0;
};
//Define specific vehicle products
class Ferrari : public Car
{
public:
    void show()
    {
        cout << "create Ferrari" << endl;
    }
};
class Maserati : public Car
{
public:
    void show()
    {
        cout << "create Maserati" << endl;
    }
};
class Maybach : public Car
{
public:
    void show()
    {
        cout << "create Maybach" << endl;
    }
};
//Define abstract lamp products
class Light
{
public:
    virtual void show() = 0;
};
//Define specific tea products
class FerrariLight : public Light
{
public:
    void show()
    {
        cout << "create Ferrari Light" << endl;
    }
};
class MaseratiLight : public Light
{
public:
    void show()
    {
        cout << "create Maserati Light" << endl;
    }
};
class MaybachLight : public Light
{
public:
    void show()
    {
        cout << "create Maybach Light" << endl;
    }
};

//Define abstract class factory
class AbstractFactory
{
public:
    //Production line for making cars and lamps
    virtual Car *createCar() = 0;
    virtual Light *createLight() = 0;
};

//Define specific factory classes
class FerrariFactory : public AbstractFactory
{
public:
    Car *createCar()
    {
        return new Ferrari();
    }
    Light *createLight()
    {
        return new FerrariLight();
    }
};
class MaybachFactory : public AbstractFactory
{
public:
    Car *createCar()
    {
        return new Maybach();
    }
    Light *createLight()
    {
        return new MaybachLight();
    }
};
class MaseratiFactory : public AbstractFactory
{
public:
    Car *createCar()
    {
        return new Maserati();
    }
    Light *createLight()
    {
        return new MaseratiLight();
    }
};

int main()
{
    unique_ptr<AbstractFactory> f1(new FerrariFactory);
    unique_ptr<AbstractFactory> f2(new MaybachFactory);
    unique_ptr<AbstractFactory> f3(new MaseratiFactory);

    //Build cars through factories
    unique_ptr<Car> c1(f1->createCar());
    unique_ptr<Car> c2(f2->createCar());
    unique_ptr<Car> c3(f3->createCar());
    c1->show();
    c2->show();
    c3->show();

    //Factory built lights
    unique_ptr<Light> l1(f1->createLight());
    unique_ptr<Light> l2(f2->createLight());
    unique_ptr<Light> l3(f3->createLight());
    l1->show();
    l2->show();
    l3->show();
}

 

Topics: Design Pattern