Design pattern learning notes - Factory Pattern

Keywords: C++ Design Pattern

Pre knowledge, six principles of design pattern

General principle: Open Close Principle
The opening and closing principle means that it is open to extensions and closed to modifications. When the program needs to be expanded, you can't modify the original code, but expand the original code to achieve a hot plug effect. So in a word, in order to make the program extensible, easy to maintain and upgrade. To achieve this effect, we need to use interfaces and abstract classes, which will be mentioned in the following specific design.

1. Single responsibility principle
There should be no more than one cause of class change, that is, each class should implement a single responsibility. Otherwise, the class should be split.

2. Liskov Substitution Principle
Liskov Substitution Principle (LSP) is one of the basic principles of object-oriented design. Richter's substitution principle says that where any base class can appear, subclasses must appear. LSP is the cornerstone of inheritance reuse. Only when the derived class can replace the base class and the function of the software unit is not affected, the base class can be truly reused, and the derived class can also add new behavior on the basis of the base class. Richter's substitution principle is a supplement to the "open close" principle. The key step in realizing the "open close" principle is abstraction. The inheritance relationship between base class and subclass is the concrete implementation of abstraction, so the Richter substitution principle is the specification of the specific steps to realize abstraction—— From Baidu Encyclopedia

In the principle of historical substitution, the methods of subclasses to parent classes should not be overridden and overloaded as much as possible. Because the parent class represents a well-defined structure and interacts with the outside world through this standardized interface, the child class should not destroy it casually.

3. Dependency Inversion Principle
This is the basis of the opening and closing principle. The specific content: interface oriented programming depends on abstraction rather than concrete. When a specific class is used in writing code, it does not interact with the specific class, but with the upper interface of the specific class.

4. Interface Segregation Principle
This principle means that there are no methods that subclasses cannot use but must implement in each interface. If not, the interface must be split. Using multiple isolated interfaces is better than using a single interface (multiple interface methods are combined into one interface).

5. Demeter Principle
That is: the less a class knows about the class it depends on, the better. In other words, no matter how complex the dependent class is, the logic should be encapsulated inside the method and provided to the outside through the public method. In this way, when the dependent class changes, it can minimize the impact on the class.

Another expression of the least known principle is to communicate only with direct friends. As long as there is a coupling relationship between classes, it is called friend relationship. Coupling can be divided into dependency, association, aggregation, composition, etc. We call the classes that appear in member variables, method parameters and method return values as direct friends. Local variables and temporary variables are not direct friends. We ask unfamiliar classes not to appear in classes as local variables.

6. Composite Reuse Principle
The principle is to try to use composition / aggregation first rather than inheritance.
 

Subject: factory mode

There are three types of factory patterns: simple factory pattern, factory pattern and abstract factory pattern. The name sounds similar, but the definition is also very vague. I don't understand why a simple factory model should be subdivided into three types and combined Design pattern c + + implementation (1) -- factory pattern_ wuzhekai's column - CSDN blog_ c + + factory mode

The examples given can be regarded as understanding what the three modes are.

F irstly, the simple factory model is introduced. Its main feature is that it needs to make judgment in the factory class to create corresponding products. When adding new products, you need to modify the factory class. It is easy to understand the code. A pure virtual class S inglecore dynamically creates a variety of single core products. The factory class factory determines whether to create products a or B according to logic.

enum CTYPE {COREA, COREB};   
class SingleCore  
{  
public:  
    virtual void Show() = 0;
};  
//Mononuclear A  
class SingleCoreA: public SingleCore  
{  
public:  
    void Show() { cout<<"SingleCore A"<<endl; }  
};  
//Single core B  
class SingleCoreB: public SingleCore  
{  
public:  
    void Show() { cout<<"SingleCore B"<<endl; }  
};  
//The only factory that can produce two types of processor cores is judged internally  
class Factory  
{  
public:   
    SingleCore* CreateSingleCore(enum CTYPE ctype)  
    {  
        if(ctype == COREA) //Factory internal judgment  
            return new SingleCoreA(); //Production nuclear A  
        else if(ctype == COREB)  
            return new SingleCoreB(); //Production nuclear B  
        else  
            return NULL;  
    }  
};  

The above code solves the problem of dynamically creating different single core products through factory classes. How does the factory model come from? The design pattern is used to solve practical problems, which raises a problem. If a new single core product is added, we need to modify the factory class interface to meet the new requirements, which violates the opening and closing principle of our expansion without modification, so there is the factory pattern. Let the factory class also be designed as a pure virtual class, and dynamically build different factories to meet our needs.

class SingleCore  
{  
public:  
    virtual void Show() = 0;
};  
//Mononuclear A  
class SingleCoreA: public SingleCore  
{  
public:  
    void Show() { cout<<"SingleCore A"<<endl; }  
};  
//Single core B  
class SingleCoreB: public SingleCore  
{  
public:  
    void Show() { cout<<"SingleCore B"<<endl; }  
};  
class Factory  
{  
public:  
    virtual SingleCore* CreateSingleCore() = 0;
};  
//Plant producing nuclear A  
class FactoryA: public Factory  
{  
public:  
    SingleCoreA* CreateSingleCore() { return new SingleCoreA; }  
};  
//Plant producing B nuclear  
class FactoryB: public Factory  
{  
public:  
    SingleCoreB* CreateSingleCore() { return new SingleCoreB; }  
};  

  We have figured out the factory mode. Let's see what's going on in the virtual factory mode. Now the CPU is developing rapidly. How should we deal with not only the single core kernel, but also the multi-core kernel? Can we get a set of muticore factory according to the factory mode? No, no, no, just add a pure virtual function interface that dynamically creates multiple cores in the factory. Let's look at the definition of the virtual factory pattern, which provides an interface to create a series of related or interdependent objects without specifying their specific classes. Isn't that easy to understand? Let's look at the code.

//Mononuclear  
class SingleCore   
{  
public:  
    virtual void Show() = 0;
};  
class SingleCoreA: public SingleCore    
{  
public:  
    void Show() { cout<<"Single Core A"<<endl; }  
};  
class SingleCoreB :public SingleCore  
{  
public:  
    void Show() { cout<<"Single Core B"<<endl; }  
};  
//Multicore  
class MultiCore    
{  
public:  
    virtual void Show() = 0;
};  
class MultiCoreA : public MultiCore    
{  
public:  
    void Show() { cout<<"Multi Core A"<<endl; }  
  
};  
class MultiCoreB : public MultiCore    
{  
public:  
    void Show() { cout<<"Multi Core B"<<endl; }  
};  
//factory  
class CoreFactory    
{  
public:  
    virtual SingleCore* CreateSingleCore() = 0;
    virtual MultiCore* CreateMultiCore() = 0;
};  
//Factory A is specially used to produce model A processor  
class FactoryA :public CoreFactory  
{  
public:  
    SingleCore* CreateSingleCore() { return new SingleCoreA(); }  
    MultiCore* CreateMultiCore() { return new MultiCoreA(); }  
};  
//Factory B, which is specially used to produce model B processors  
class FactoryB : public CoreFactory  
{  
public:  
    SingleCore* CreateSingleCore() { return new SingleCoreB(); }  
    MultiCore* CreateMultiCore() { return new MultiCoreB(); }  
}; 

Great article. The code is relatively simple, and the UML diagram is not stolen. If you want to see it, jump to the reference link Design pattern c + + implementation (1) -- factory pattern_ wuzhekai's column - CSDN blog_ c + + factory mode

Posted by plex303 on Tue, 23 Nov 2021 02:49:06 -0800