2.1 Modal Motivation

Consider a simple software application scenario, a software system can provide a number of different appearance button (such as radio buttons, rectangular button, diamond button, etc.), these buttons are derived from the same base class, but after the inherited base class different subclasses to modify the part properties so that they can present different appearance, if we want to use these buttons, Don’t need to know the specific button in the name of the class, said just need to know the button class a parameter, and provides a call convenient method, into the parameter method can return a corresponding button object, now to change the system, design a button factory class to no longer responsible for all products to create, Instead, we delegate the creation of concrete buttons to specialized factory subclasses. We define an abstract button factory class and then define concrete factory classes to generate circular buttons, rectangular buttons, diamond buttons, and so on, which implement the methods defined in the abstract button factory class. To this structure as a result of this abstract concrete under the condition of the factory class can be changed without introducing new products, if there is a new type button, only need for this new type of button to create a specific factory class can get the new button on the instance, this feature will make the factory method pattern has surmounted the advantages of simple factory pattern, More in line with the “open and closed principle”.

2.2 Definition and characteristics of the mode

The Factory Method Pattern is also called the Factory Pattern, also called the Virtual Constructor Pattern or the Polymorphic Factory Pattern, which belongs to the class creation Pattern. Parent in factory method pattern, the factory is responsible for defining public interfaces, objects created products and factories subclass object is responsible for generating the specific products, the purpose is to delay product class instantiation operations to complete, factory subclasses by factory subclasses to determine exactly which a specific product class to instantiate.

We call the objects being created “products” and the objects creating the products “factories.” If the number of products to be created is small, it can be done with only one factory class. This pattern is called “Simple Factory pattern”, which does not belong to GoF’s 23 classic design patterns. Its disadvantage is that adding new products violates the “open closed principle”. The “factory method pattern” introduced in this section is a further abstraction of the simple factory pattern, which has the benefit of enabling the system to introduce new products without modifying the original code, i.e. satisfying the open closed principle.

The main advantages of the factory method pattern are:

  • In the factory method pattern, the factory method is used to create the product that the customer needs, and it also hides the details of which specific product class will be instantiated from the customer. The user only needs to care about the factory for the desired product, not the creation details, or even the class name of the specific product class.
  • The polymorphism design based on factory role and product role is the key of factory method pattern. It enables the factory to decide which product object to create, and the details of how to create this object are completely encapsulated within the specific factory. The factory method pattern is also called polymorphic factory pattern because all concrete factory classes have the same abstract parent class.
  • Another advantage of using the factory method pattern is that when you add a new product to the system, you don’t need to modify the abstract factory and the interface provided by the abstract product, you don’t need to modify the client, or you don’t need to modify other concrete factories and concrete products, you just need to add a concrete factory and concrete products. In this way, the scalability of the system has become very good, fully in line with the “open and closed principle”.

Its disadvantages are:

When a new product is added, new concrete product classes are written, and corresponding concrete factory classes are provided. The number of classes in the system increases in pairs, increasing the complexity of the system to some extent, as more classes need to be compiled and run, bringing some extra overhead to the system. Taking into account the scalability of the system, an abstraction layer is introduced, which is defined in the client code, increasing the abstraction and difficulty of understanding the system. In addition, DOM and reflection technologies may be used in the implementation, increasing the difficulty of the system.

2.3 Structure and implementation of the mode

Factory method pattern consists of abstract factory, concrete factory, abstract product and concrete product. This section analyzes its basic structure and implementation method.

2.3.1 Pattern structure

The main roles of the factory method pattern are as follows. Abstract Factory: Provides an interface for creating products through which callers create products by accessing the Factory method newProduct() of a concrete Factory. ConcreteFactory: Abstract methods in abstract factories are implemented to create concrete products. Abstract Product: Defines the specification of the Product, describing the main features and functions of the Product. Concreteproducts: Interfaces that implement abstract product roles are created by concrete factories and correspond to concrete factories. Its structure is shown in Figure 1.

Figure 1 Structure diagram of the factory method pattern

Here’s a distinction between the factory method pattern and the simple factory pattern. The simple factory pattern requires determining what type of object to produce in the factory class. The factory method pattern leaves this work to the client. Each type of object has its own factory, and the client generates different factories according to its own needs, and then produces the objects it needs. The factory method pattern reduces the degree of coupling between the class and the client compared to the simple factory pattern. The most important point is that you don’t have to change the original code when you need to add other classes. Just use the factory to add the response and the class. This follows the open-closure principle. The simple factory model actually breaks the open-closed principle.

2.3.2 Implementation of the pattern

/**Includes*********************************************************************/
#include <iostream>

/**namespace********************************************************************/
using namespace std;

class Product
{
public:
    virtual void Show(a) = 0;
};

class ConcreteProduct1 : public Product
{
public:
    void Show(a)
    {
        cout<< "I'm ConcreteProduct1"<<endl; }};class ConcreteProduct2 : public Product
{
public:
    void Show(a)
    {
        cout<< "I'm ConcreteProduct2"<<endl; }};class Creator
{
public:
    virtual Product *CreateProduct(a) = 0;
};

class ConcreteCreator1 : public Creator
{
public:
    Product *CreateProduct(a)
    {
        return new ConcreteProduct1 ();
    }
};

class ConcreteCreator2 : public Creator
{
public:
    Product *CreateProduct(a)
    {
        return new ConcreteProduct2();
    }
};


/** * @brief main function * @param argc argv * @retval None */
int main(int argc, char *argv[])
{
    Creator *factoryA = new ConcreteCreator1(a); Product *productA = factoryA->CreateProduct(a); productA->Show(a); Creator *factoryB =new ConcreteCreator2(a); Product *productB = factoryB->CreateProduct(a); productB->Show(a);if(factoryA ! =NULL)
    {
        delete factoryA;
        factoryA = NULL;
    }

    if(productA ! =NULL)
    {
        delete productA;
        productA = NULL;
    }

    if(factoryB ! =NULL)
    {
        delete factoryB;
        factoryB = NULL;
    }

    if(productB ! =NULL)
    {
        delete productB;
        productB = NULL;
    }
    return 0;
}
Copy the code

2.4 Application Scenarios of Mode

The factory method pattern can be used in some situations, whereby a class doesn’t know the class of the object it needs: in a factory method pattern, the client doesn’t need to know the class name of a specific product class, just the corresponding factory, because the specific product object is created by the factory class. The client needs to know the factory class to create the specific product.  a class through its subclasses to specify which object to be created, in the factory method pattern, for the abstract factory class only need to provide an interface for creating products, and by its subclasses to determine specific to create objects, using object-oriented polymorphism and substitution principle on the Richter scale, when the program is run by a subclass overrides the superclass object, so as to make the system more scalable. A client uses a system to delegate object creation to one of several factory subclasses, allowing the client to use a system regardless of which factory subclass creates a product subclass and specify it dynamically if needed. The class name of a specific factory class can be stored in a configuration file or database.

2.5 Schema extensions

Use multiple factory methods: Multiple factory methods can be defined in an abstract factory role to enable specific factory roles to implement these different factory methods, which can contain different business logic to meet the needs of different product objects.

Reuse of product objects: Factory objects store created products in a collection (such as groups, lists, and so on) and then query the collection based on customer requests for products. If there is a product object that meets the requirements, the product is directly returned to the client. If there is no such product object in the collection, a new satisfying product object is created, added to the collection, and returned to the client.

Loss of polymorphism and schema degradation: If the factory returns only a concrete product object, it defeats the purpose of the factory method and degrades, and the factory method pattern is no longer there. In general, factory objects should have an abstract parent type. If there is only one concrete factory class in the factory hierarchy, the abstract factory can be omitted and degradation will occur. When there is only one concrete factory in which all product objects can be created, and the factory method is designed as a static method, the factory method pattern degrades to a simple factory pattern.

2.6 summarize

The factory method pattern, also known as the factory pattern, belongs to the class-creation pattern. Parent in factory method pattern, the factory is responsible for defining public interfaces, objects created products and factories subclass object is responsible for generating the specific products, the purpose is to delay product class instantiation operations to complete, factory subclasses by factory subclasses to determine exactly which a specific product class to instantiate.

The factory method pattern has four roles: abstract products are interfaces that define products, and they are supertypes of objects created by the factory method pattern, i.e. common parent classes or interfaces of product objects; Concrete products implement abstract product interfaces, and concrete products of a certain type are created by specific concrete factories, often corresponding to each other. The abstract factory declares a factory method that returns a product. It is the core of the factory method pattern, and any factory class that creates objects in the pattern must implement this interface. A concrete factory is a subclass of an abstract factory class that implements factory methods defined in an abstract factory and can be called by a customer to return an instance of a concrete product class.

The factory method pattern is a further abstraction and extension of the simple factory pattern. The factory method pattern retains the advantages of the simple factory pattern and overcomes its disadvantages by using object-oriented polymorphism. In the factory method pattern, the core factory class is no longer responsible for the creation of all products, but hands off the specific creation to subclasses. This core class is only responsible for giving the interfaces that a particular factory must implement, not the details of how the product class is instantiated, allowing the factory method pattern to allow the system to introduce new products without changing the factory role.

The main advantage of factory method mode is that it does not need to modify the existing system when adding new product classes, and encapsulates the creation details of product objects, so the system has good flexibility and scalability. Its disadvantage is that new factories need to be added when new products are added, which leads to a pairwise increase in the number of system classes and increases the complexity of the system to a certain extent.

The factory method pattern applies when: a class does not know the object it needs; A class specifies which object to create by subclass; Delegate object creation to one of multiple factory subclasses. Clients can use it without caring which factory subclass creates the product subclass and specify it dynamically if necessary.

Appendix: Simple Factory pattern

Simple Factory Pattern: Also known as Static Factory Method Pattern, it belongs to the class creation Pattern. In the simple factory pattern, you can return instances of different classes depending on the parameters. The simple factory pattern specifically defines a class that is responsible for creating instances of other classes, which usually have a common parent class.

The simple Factory pattern contains the following roles: Factory: Factory role The Factory role is responsible for implementing the internal logic that creates all instances

Product: Abstract Product Roles Abstract Product roles are the parent classes of all objects created and are responsible for describing the common interfaces shared by all instances

A ConcreteProduct role is a creation target, and all created objects act as instances of a concrete class for this role.

Separating object creation from the business processing of the object itself reduces the coupling of the system, making both relatively easy to modify.

The call to the factory class factory method, because the factory method is a static method, it is convenient to use, can be called directly by the name of the class, and you just need to pass in a simple parameters, in the actual development, can also be in a call to save the incoming parameters in an XML format, such as the configuration file, modify parameters do not need to modify any source code.

The biggest problem of the simple factory model is that the responsibilities of the factory class are relatively heavy. Adding new products requires modifying the judgment logic of the factory class, which is contrary to the open and closed principle.

The point of the simple factory pattern is that when you need something, you can just pass in the right argument and get the object you need without knowing the details of how it was created.

Advantages of the simple factory pattern

  • The factory class contains the necessary judgment logic to decide when to create an instance of a product class, freeing clients from the responsibility of directly creating product objects and simply “consuming” the product; The simple factory pattern achieves this separation of responsibilities by providing specialized factory classes for creating objects.
  • The client does not need to know the class name of the created specific product class, but only needs to know the corresponding parameters of the specific product class. For some complex class names, simple factory mode can reduce the memory of users.
  • By introducing configuration files, new specific product classes can be replaced and added without modifying any client code, increasing the flexibility of the system to some extent.

Disadvantages of the simple factory pattern

  • Because the factory class centralizes all product creation logic, if it doesn’t work properly, the entire system suffers.
  • Using the simple factory pattern will increase the number of classes in the system, increasing the complexity and understanding of the system at some point.
  • It is difficult to expand the system. Once new products are added, the factory logic has to be modified. If there are many product types, the factory logic may be too complex, which is not conducive to the expansion and maintenance of the system.
  • The simple factory pattern uses a static factory approach that prevents the factory roles from forming an inheritance-based hierarchy.

Apply to the environment

The simple factory pattern can be used when:

  • The factory class is responsible for creating fewer objects: Because there are fewer objects created, the business logic in the factory method is not too complicated.
  • The client only knows the parameters passed into the factory class, not how the object is created: the client doesn’t need to care about the creation details or even remember the class name, just the parameters that the type corresponds to.
/**Includes*********************************************************************/
#include <iostream>

/**namespace********************************************************************/
using namespace std;

typedef enum ProductTypeTag
{
    TypeA,
    TypeB,
    TypeC
}PRODUCTTYPE;

// Here is the product class
class Product
{
public:
    virtual void Show(a) = 0;
};

class ProductA : public Product
{
public:
    void Show(a)
    {
        cout<<"I'm ProductA"<<endl; }};class ProductB : public Product
{
public:
    void Show(a)
    {
        cout<<"I'm ProductB"<<endl; }};class ProductC : public Product
{
public:
    void Show(a)
    {
        cout<<"I'm ProductC"<<endl; }};// Here is the Factory class
class Factory
{
public:
    Product* CreateProduct(PRODUCTTYPE type)
    {
        switch (type)
        {
        case TypeA:
            return new ProductA(a);case TypeB:
            return new ProductB(a);case TypeC:
            return new ProductC(a);default:
            return NULL; }}};int main(int argc, char *argv[])
{
    // First, create a factory object
    Factory *ProductFactory = new Factory(a); Product *productObjA = ProductFactory->CreateProduct(TypeA);
    if(productObjA ! =NULL)
        productObjA->Show(a); Product *productObjB = ProductFactory->CreateProduct(TypeB);
    if(productObjB ! =NULL)
        productObjB->Show(a); Product *productObjC = ProductFactory->CreateProduct(TypeC);
    if(productObjC ! =NULL)
        productObjC->Show(a);delete ProductFactory;
    ProductFactory = NULL;

    delete productObjA;
    productObjA = NULL;

    delete productObjB;
    productObjB = NULL;

    delete productObjC;
    productObjC = NULL;

    return 0;
}
Copy the code