Bootstrap

C++ 常见设计模式总结


1.面向对象中有哪些设计原则?


2.开闭原则,哪些原则与它相关,其关系


3.里氏替换原则原则

#include <iostream>
using namespace std;

class ZooShow {
public:
    void Show() {
        if (Show0()) {
            PlayGame();
        }
        Show1();
        Show2();
        Show3();
    }

private:
    void PlayGame() {
        cout << "after Show0, then play game" << endl;
    }
    

protected:
    virtual bool Show0() {
        cout << "show0" << endl;
        if (!expired) {
            return true;
        }
        return false;
    }
    virtual void Show2() {
        cout << "show2" << endl;
    }
    virtual void Show1() {
        
    }
    virtual void Show3() {

    }
    bool expired;
};

class ZooShowEx1 : public ZooShow {
protected:
    virtual bool Show0() {
        cout << "ZooShowEx1 show0" << endl;
        if (! expired) { //里氏替换
            return true;
        }
        return false;
    }
    virtual void Show2() {

    }
};

4.迪米特原则


5.依赖倒置原则


6.单例模式多线程


单线程环境下的单例模式:

class Singleton {
public:
    static Singleton *GetInstance() {
        if (_instance == nullptr) {
            _instance = new Singleton();
            std::atexit(Destructor);
        }
        return _instance;
    }
private:
    static void Destructor() {
        if (_instance != nullptr) {
            delete _instance;
            _instance = nullptr;
        }
    }
    Singleton() {}
    ~Singleton() {}
    Singleton(const Singleton &clone) {}
    Singleton & operator = (const Singleton &) {}
    static Singleton *_instance;
};

Singleton * Singleton::_instance = nullptr;

多线程环境互斥锁

#include <mutex>

class Singleton {
public:
    static Singleton *GetInstance() {
        // std::lock_guard<std::mutex> lock(_mutex);  //加锁粒度大
        if (_instance == nullptr) {
            std::lock_guard<std::mutex> lock(_mutex);
            if (_instance == nullptr) {
                _instance = new Singleton();  //多线程环境下编译器和CPU对程序进行优化
                // 1. 分配内存
                // 2. 调用构造函数
                // 3. 返回指针,赋值运算
                // 多线程环境下可能会优化为1 3 2
                std::atexit(Destructor);
            }
        }
        return _instance;
    }
private:
    static void Destructor() {
        if (_instance != nullptr) {
            delete _instance;
            _instance = nullptr;
        }
    }
    Singleton() {}
    ~Singleton() {}
    Singleton(const Singleton &clone) {}
    Singleton & operator = (const Singleton &) {}
    static Singleton *_instance;
    static std::mutex _mutex;
};

Singleton * Singleton::_instance = nullptr;
std::mutex Singleton::_mutex;
#include <mutex>
#include <atomic>
class Singleton {
public:
    static Singleton *GetInstance() {
        Singleton *temp = _instance.load(std::memory_order_relaxed);
        std::atomic_thread_fence(std::memory_order_acquire);
        if (temp == nullptr) {
            std::lock_guard<std::mutex> lock(_mutex);
            temp = _instance.load(std::memory_order_relaxed);
            if (temp == nullptr) {
                temp = new Singleton();  //多线程环境下编译器和CPU对程序进行优化
                std::atomic_thread_fence(std::memory_order_release);
                _instance.store(temp, std::memory_order_relaxed);
                // 1. 分配内存
                // 2. 调用构造函数
                // 3. 返回指针,赋值运算
                // 多线程环境下可能会优化为1 3 2
                std::atexit(Destructor);
            }
        }
        return temp;
    }
private:
    static void Destructor() {
        Singleton *temp = _instance.load(std::memory_order_relaxed);
        if (temp != nullptr) {
            delete temp;
            temp = nullptr;
            _instance.store(temp, std::memory_order_relaxed);
        }
    }
    Singleton() {}
    ~Singleton() {}
    Singleton(const Singleton &clone) {}
    Singleton & operator = (const Singleton &) {}
    static std::atomic<Singleton *> _instance;
    static std::mutex _mutex;
};

std::atomic<Singleton *> Singleton::_instance;
std::mutex Singleton::_mutex;

7.什么是工厂模式?什么是抽象工厂?


7.1 简单工厂模式
  1. 定义:根据参数的不同返回不同类的实例,被创建的实例通常具有共同的基类。
  2. 结构:
    • 工厂:根据客户提供的具体产品类的参数,创建具体产品的实例。
    • 抽象产品:具体产品类的基类,包含创建产品的公共方法。
    • 具体产品:抽象产品的派生类,特定产品的实现方法。
  3. 优点:
    • 工厂类提供创建产品的具体方法,客户不必参与创建过程。
    • 客户只需要知道对应产品参数即可。
  4. 缺点:
    • 客户增加产品时,需要修改工厂类逻辑,违背开闭原则。
7.2 工厂方法模式
  1. 定义:工厂类中针对不同的产品设计不同的工厂,每种工厂是生成特定的产品(解决简单工厂模式存在的不足)。定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。
  2. 结构:
    • 抽象工厂:所有生产具体产品的工厂类的基类,提供工厂类的公共方法。
    • 具体工厂:生产具体的产品工厂类。
    • 抽象产品:所有产品的基类,提供产品类的公共方法。
    • 具体产品:具体的产品类。
  3. 优点:
    • 工厂方法用于创建客户所需产品,同时向客户隐藏细节,用户只需关心所需产品对应的工厂;
    • 工厂自主决定创建何种产品,并且创建过程封装在具体工厂对象内部,多态性设计是工厂方法模式的关键;
    • 新加入产品时,无需修改原有代码,增强了系统的可扩展性,符合开闭原则。
  4. 缺点:
    • 添加新的产品时,引入新的产品工厂,增加了系统复杂度;
    • 工厂和产品中都引入抽象层,增加了系统的抽象层次。
7.3 抽象工厂模式
  1. 定义:一个工厂不止生产一种产品,生产一类产品。提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
  2. 结构:
    • 抽象工厂:所有生产具体产品的工厂类的基类,提供工厂类的公共方法。
    • 具体工厂:生产具体的产品工厂类,可以生产多种同类相关的产品。
    • 抽象产品:所有产品的基类,提供产品类的公共方法。
    • 具体产品:具体的产品类。
  3. 优点:
    • 工厂方法用于创建客户所需产品,同时向客户隐藏细节,用户只需关心所需产品对应的工厂;
    • 新加入产品时,无需修改原有代码,增强了系统的可扩展性,符合开闭原则。
  4. 缺点:
    • 添加新产品时需要修改抽象层代码,对原有系统改动较大。
#include <string>

// 实现导出数据的接口
class IExport {
public:
    virtual bool Export(const std::string &data) = 0;
    virtual ~IExport() {};
};

class ExportXml : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportJson : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class ExportTxt : public IExport {
public:
    virtual bool Export(const std::string &data) {
        return true;
    }
};

class IExportFactory {
public:
    IExportFactory() {
        _export = nullptr;
    }
    virtual ~IExportFactory() {
        if (_export) {
            delete _export;
            _export = nullptr;
        }
    }
    bool Export(const std::string &data) {
        if (_export == nullptr) {
            _export = NewExport();
        }
        return _export->Export(data);
    }
protected:
    virtual IExport * NewExport(/*---*/) = 0;
private:
    IExport* _export;
};

class ExoortXmlFactory : public IExportFactory {
protected:
    virtual IExport * NewExport(/*---*/) {
        // 可能有其它很多操作
        IExport * temp = new ExportXml();
        return temp;
    }
};

class ExoortJsonFactory : public IExportFactory {
protected:
    virtual IExport * NewExport(/*---*/) {
        // 可能有其它很多操作
        IExport * temp = new ExportJson();
        return temp;
    }
};

class ExoortTxtFactory : public IExportFactory {
protected:
    virtual IExport * NewExport(/*---*/) {
        // 可能有其它很多操作
        IExport * temp = new ExportTxt();
        return temp;
    }
};

int main() {
    IExportFactory *factory = new ExportTxtFactory();
    factory->Export("hello world");
    return 0;
}

8.什么是代理模式?应用场景是什么?


class ISsubject {
public:
    virtual void Handle() = 0;
    virtual ~ISsubject() {}
};

class RealSubject : public ISsubject {
public:
    virtual void Handle() {

    }
};
// 保护代理 
class Proxy1 : public ISsubject {
public:
    Proxy1(ISsubject * subject) : _subject(subject) {}
    virtual void Handle() {
        // 在访问RealSubject 之前一些处理
        // if (不满足条件)
        // return;
        _subject->Handle();
        count++;
        // 在访问RealSubject 之后做一些处理
    }
private:
    ISsubject * _subject;
    static int count;
};
int Proxy1::count = 0;

// 远程代理
class Proxy2 : public ISsubject {
public:
    virtual void Handle() {
        // 在访问RealSubject之前做一些特殊处理
        // 发送数据到远端 网络处理 同步非阻塞 ntyco c协程
        // IResult * val = rpc->call("RealSubject", "Handle");
        // 在访问RealSubject之后做一些处理
    }
private:
    /*void callback(IResult * val) {
        // 在访问RealSubject 之后做一些处理
    }
    */
};

// 虚代理
class Proxy3 : public ISsubject {
public:
    Proxy1(ISsubject *subject) : _subject(subject), _loaded(false) {}
    virtual void Handle() {
        if (! _loaded) {
            _loaded = true;
            //加载资源
        }
        _subject->Handle();
    }
private:
    ISsubject* _subject;
    bool _loaded;
};

9.什么是装饰器模式?应用模式是什么?

#include <iostream>

using namespace std;

class Context {
public:
    bool isMgr;
    // User user;
    // double groupsale;
};

class CalcBonus {
public:
    CalcBonus(CalcBonus * c = nullptr) : cc(c) {}
    virtual double Calc(Context &ctx) {
        return 0.0; 
    }
    virtual ~CalcBonus() {}

protected:
    CalcBonus* cc;
};

class CalcMouthBonus : public CalcBonus {
public:
    CalcMouthBonus(CalcBonus * c) : CalcBonus(c) {}
    virtual double Calc(Context &ctx) {
        double mbonus /*计算自己的*/;
        return mbonus + cc->Calc(ctx);
    }
};

class CalcSumBonus : public CalcBonus {
public:
    CalcSumBonus(CalcBonus * c) : CalcBonus(c) {}
    virtual double Calc(Context &ctx) {
        double mbonus /*计算自己的*/;
        return mbonus + cc->Calc(ctx);
    }
};

class CalcCycleBonus : public CalcBonus {
public:
    CalcCycleBonus(CalcBonus * c) : CalcBonus(c) {}
    virtual double Calc(Context &ctx) {
        double mbonus /*计算自己的*/;
        return mbonus + cc->Calc(ctx);
    }
};

int main() {
    Context ctx1;
    CalcBonus *base = new CalcBonus();
    CalcBonus *cb2 = new CalcSumBonus(base);
    CalcBonus *cb1 = new CalcMouthBonus(cb2);
    cb2->Calc(ctx1);

    return 0;
}

10.什么是组合模式?应用场景是什么?

class IComponent {
public:
    IComponent(/* args */);
    ~IComponent();
    virtual void Execute() = 0;
    virtual void AddChild(IComponent *ele) {}
    virtual void RemoveChild(IComponent *ele) {}
};

class Leaf : public IComponent {
public:
    virtual void Execute() {
        cout << "leaf execute" << endl;
    }
};

class Composite : public IComponent {
private:
    std::list<IComponent *> _list;
public:
    virtual void AddChild(IComponent *ele) {
        // 
    }
    virtual void RemoveChild(IComponent *ele) {

    }
    virtual void Execute() {
        for (auto iter = _list.begin(); iter != _list.end(); iter ++) {
            iter->Execute();
        }
    }
};

11.什么是责任链模式?应用场景是什么?


12.什么是模板方法? 应用场景是什么?


13.什么是策略模式?应用场景是什么?


14.什么是观察者模式?应用场景是什么?

参考

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,点击立即学习:https://course.0voice.com/v1/course/intro?courseId=5&agentId=0

;