C++ design patterns-knowledge review summary

Simple factory pattern

The steps to create and use simple factory pattern related classes are as follows:

(1) Create a new class, which can be called a factory class. For the simple factory pattern, only one factory class is required.

(2) Add a public member function to this factory class, and use this function to create the objects we need. This function is generally called a factory function.

(3) Regarding usage, first create a factory class object, and then call the factory function through this object, so that an instance object of the specified type can be produced.


#include<iostream>
#include<memory>
using namespace std;

class Animal
{
public:
    virtual void sound(){};
};

class Dog : public Animal
{
public:
    void sound()override
    {
        cout<<"汪汪"<<endl;
    }  
};

class Cat : public Animal
{
public:
    void sound()override
    {
        cout<<"喵喵"<<endl;
    }
};

enum class Type{DOG,CAT};

class Animalfactory
{
public:
    Animalfactory(){};
    ~Animalfactory(){};
    Animal * ptr = nullptr;
    Animal* createAnimal(Type type)
    {
        switch (type)
        {
        case Type::DOG:
            ptr = new Dog;
            break;

        case Type::CAT:
            ptr = new Cat;
            break;
        }
        
        return ptr;
    }
};

int main()
{
    Animalfactory * fac = new Animalfactory();
    std::shared_ptr<Animal> p = std::shared_ptr<Animal>(fac->createAnimal(Type::DOG));
    
    p->sound();
    return 0;
}

 abstract factory pattern

The abstract factory pattern is suitable for more complex and changeable business scenarios. Generally speaking, it is to add an abstract class to a series of components with the same function but changing attributes, so that subsequent expansion can be very convenient, and then combined with the factory class We can create the objects we need.


The abstract factory pattern obeys the opening and closing principle, but the factory pattern does not.

The class corresponding to the object created by the factory pattern does not need to provide an abstract class [there are no variable factors in this product class component] The
class corresponding to the object created by the abstract factory pattern has an abstract base class [there are variable factors in this product class component]

The following code takes car manufacturing as an example. It is assumed that electric cars and fuel cars need to be built, and the two cars require different engine types. Therefore, it is necessary to create an electric vehicle factory and a fuel vehicle factory. The two automobile factory classes are the base class of the gas field factory.

#include <iostream>
#include <memory>

// 抽象产品:汽车零部件
class CarPart {
public:
    virtual ~CarPart() {}
    virtual void start() const = 0;
};

// 具体产品:电动汽车电机
class ElectricCarMotor : public CarPart {
public:
    void start() const override {
        std::cout << "Electric car motor started." << std::endl;
    }
};

// 具体产品:燃油汽车发动机
class GasolineEngine : public CarPart {
public:
    void start() const override {
        std::cout << "Gasoline engine started." << std::endl;
    }
};

// 抽象工厂:汽车工厂
class CarFactory {
public:
    virtual ~CarFactory() {}
    virtual std::unique_ptr<CarPart> createCarPart() const = 0;
};

// 具体工厂:电动汽车工厂
class ElectricCarFactory : public CarFactory {
public:
    std::unique_ptr<CarPart> createCarPart() const override {
        return std::make_unique<ElectricCarMotor>();
    }
};

// 具体工厂:燃油汽车工厂
class GasolineCarFactory : public CarFactory {
public:
    std::unique_ptr<CarPart> createCarPart() const override {
        return std::make_unique<GasolineEngine>();
    }
};

int main() {
    // 使用电动汽车工厂创建一个电动汽车
    std::unique_ptr<CarFactory> electricCarFactory = std::make_unique<ElectricCarFactory>();
    std::unique_ptr<CarPart> carPart = electricCarFactory->createCarPart();
    carPart->start(); // 输出:Electric car motor started.

    // 使用燃油汽车工厂创建一个燃油汽车
    std::unique_ptr<CarFactory> gasolineCarFactory = std::make_unique<GasolineCarFactory>();
    carPart = gasolineCarFactory->createCarPart();
    carPart->start(); // 输出:Gasoline engine started.

    return 0;
}

adapter mode

Adapter Pattern is a structural design pattern that converts the interface of a class into another interface expected by the client. Adapters allow otherwise incompatible classes to work together.

The adapter pattern includes the following roles:

  1. Target interface (Target): The interface expected by the client, that is, the interface the client needs to use.

  2. Source interface (Adaptee): The interface that needs to be adapted, that is, the interface that originally does not meet the needs of the client.

  3. Adapter: A class that converts a source interface into a target interface.

Common application scenarios of the adapter pattern include:

  1. When using an existing class and finding that its interface does not meet the requirements, you can use the adapter pattern to convert its interface into the interface expected by the client.

  2. During the development process, you can use the adapter pattern to be compatible with different interfaces and frameworks.

To put it simply: convert the interface of a class into another interface that the user wants, so that incompatible objects can cooperate with each other and work together. This mode is called the adapter mode.

#include<iostream>
#include<string>
#include<memory>
using namespace std;

//目标接口
class MedioPlayer
{
public:
    virtual void play(string filename) = 0;
};


//源接口
class Vedio
{
public:
    virtual void play(string filename) = 0;
};

class Mp4 : public Vedio
{
public:
    void play(string filename)
    {
        std::cout<<"play mp4 file"<<std::endl;
    }
};

class Vlc : public Vedio
{
public:
    void play(string filename)
    {
        std::cout<<"play Vlc"<<std::endl;
    }
};

//适配器
class MedioPlayerApapter : public MedioPlayer
{
public:
    MedioPlayerApapter(Vedio *v):vedio(v){}
    ~MedioPlayerApapter(){}
    void play(string filename) override
    {
        if (filename.find(".mp4") != std::string::npos) vedio->play(filename);
        else if (filename.find(".vlc") != std::string::npos) vedio->play(filename);
        else std::cout<<"Invalid vedio"<<std::endl;
    }

    void setVedio(Vedio *v)
    {
        vedio = v;
    }

private:
    Vedio *vedio;
};

int main()
{
    std::shared_ptr<Vedio> mp4 = std::make_shared<Mp4>();
    std::shared_ptr<Vedio> vlc = std::make_shared<Vlc>();


    std::shared_ptr<MedioPlayerApapter> p = std::make_shared<MedioPlayerApapter>(mp4.get());
    p->play("xx.mp4");

    p->setVedio(vlc.get());
    p->play("xx.vlc");

}

 Later, more common design patterns will be used and then updated.

Guess you like

Origin blog.csdn.net/weixin_40582034/article/details/131570919