C++设计模式之手撕

以下详细介绍几种常见的设计模式:1.单例模式 2.工厂模式 3.观察者模式 4.代理模式 5.适配器模式(目前只跟新单例模式和工厂模式)

一:单例模式(区分懒汉和饿汉):

注解(此方案为饿汉式,成熟且简单的方案,大厂都在用):

1.设置友元的目的是:父类可以调用子类的构造,子类向父类开放构造函数

2.使用模板类,提高复用性

3.使用静态变量,保证只初始化一次,并且可以自动释放内存,无须考虑内存泄露

4.把构造函数私有化,防止外部调用

5.自己初始化赋值构造函数和拷贝构造函数

6.父类析构设置虚函数,保证可以释放指向父类指针的子类内存可以释放

#include 
#include 
template
class Singleton
{
public:

    static T& GetInstance()
    {
        //静态局部区域  会自动释放  堆才需要手动释放
        static T instance;
        return instance;
    }

protected:
    virtual ~Singleton() {};   //destruct
    Singleton() {}  //construct
    Singleton(const Singleton& clone) {}
    Singleton& operator=(const Singleton&) {}
};

class DesignPattern : public Singleton
{
    friend class Singleton;
public:
    ~DesignPattern() {}
private:
    DesignPattern() = default;  //construct
    DesignPattern(const DesignPattern& clone) = delete;
    DesignPattern& operator=(const DesignPattern&) = delete;
};

 注解(此方案为懒汉式,version 3.1 懒加载单例):

缺点:多线程有创建多个对象的风险

//Version3.1
class Singleton
{
public:
    static Singleton* GetInstance()
    {
        if (_instance == nullptr)
        {
            _instance = new Singleton();
            //进程退出调用
            atexit(Destructor);
        }

        return _instance;
    }

private:
    static void Destructor()
    {
        if (_instance != nullptr)
        {
            delete _instance;
            _instance = nullptr;
        }
    }
    Singleton() {}  //construct
    ~Singleton();   //delstruct
    Singleton(const Singleton& clone) {}
    Singleton& operator=(const Singleton&) {}
    static Singleton* _instance;
};

 注解(此方案为懒汉式,version 3.2 懒加载单例):

改进:支持多线程访问

缺点:(知识点)构造函数分三个步骤:1.分配内存,2.调用构造 3. 返回指针

cpu 多线程 有reorder 操作 1.3.2 未初始化,没有调用构造野指针 ,所有字段都有,但是都是乱码。

//Version3.2   lazy load
//multil thread
#include 
class Singleton
{
public:
    static Singleton* GetInstance()
    {
        //std::lock_guard lock(_mutex);     //3.1    效率太低没必要频繁加锁  1----9999  互斥锁会切换线程

        if (_instance == nullptr)
        {
            std::lock_guard lock(_mutex);    //3.2  拿到锁马上new,有重复创建的风险 需要二次判断

            if (_instance == nullptr)  //需要二次判断
            {
                //cpu 多线程 有reorder 操作 1.3.2 未初始化 没有调用构造 野指针 所有字段都有,但是都是乱码
                //1.分配内存,2.调用构造 3. 返回指针
                _instance = new Singleton();

                //进程退出调用
                atexit(Destructor);

            }
        }

        return _instance;
    }

private:
    static void Destructor()
    {
        if (_instance != nullptr)
        {
            delete _instance;
            _instance = nullptr;
        }
    }
    static std::mutex _mutex;
    Singleton() {}  //construct
    ~Singleton();   //delstruct
    Singleton(const Singleton& clone) {}
    Singleton& operator=(const Singleton&) {}
    static Singleton* _instance;
};

 注解(此方案为懒汉式,version 3.3 懒加载单例):

改进:解决reorder问题

//Version3.3   lazy load
//multil thread   解决reorder问题  volitle
#include 
#include 
class Singleton
{
public:
    static Singleton* GetInstance()
    {
        Singleton* tmp = _instance.load(std::memory_order_relaxed);
        std::_Atomic_thread_fence(std::memory_order_acquire);

        if (tmp == nullptr)
        {
            std::lock_guard lock(_mutex);    //3.2  拿到锁马上new,有重复创建的风险 需要二次判断

            if (tmp == nullptr)  //需要二次判断
            {
                //cpu 多线程 有reorder 操作 1.3.2 未初始化 没有调用构造 野指针 所有字段都有,但是都是乱码
                //1.分配内存,2.调用构造 3. 返回指针
                tmp = new Singleton();
                std::_Atomic_thread_fence(std::memory_order_release);
                _instance.store(tmp, std::memory_order_relaxed);
                //进程退出调用
                atexit(Destructor);

            }
        }

        return tmp;
    }

private:
    static void Destructor()
    {
        Singleton* tmp = _instance.load(std::memory_order_relaxed);

        if (tmp != nullptr)
        {
            delete tmp;
        }
    }
    static std::mutex _mutex;
    Singleton() {}  //construct
    ~Singleton();   //delstruct
    Singleton(const Singleton& clone) {}
    Singleton& operator=(const Singleton&) {}
    static std::atomic _instance;
};

一:工厂模式:

以下三个版本层层递进,方便理解并最终手撕!

注解:version1.1

#pragma once
using namespace std;
#include 
#include 
class IExport
{
public:
    virtual bool Export(const string& data) = 0;
    virtual~IExport() {};
};

class ExportXml: public IExport
{
public:
    virtual bool Export(const string& data)
    {
        cout << "ExportXml:  " << data << endl;
        return true;
    }
};

class ExportJson : public IExport
{
public:
    virtual bool Export(const string& data)
    {
        cout << "ExportJson:   " << data << endl;
        return true;
    }
};

class ExportText : public IExport
{
public:
    virtual bool Export(const string& data)
    {
        cout << "ExportText:  " << data << endl;
        return true;
    }
};


注解二:版本1.2

#pragma once
using namespace std;
#include 
#include 

class IExport
{
public:
    virtual bool Export(const string& data) = 0;
    virtual~IExport() {};
};

class ExportXml : public IExport
{
public:
    virtual bool Export(const string& data)
    {
        cout << "ExportXml:  " << data << endl;
        return true;
    }
};

class ExportJson : public IExport
{
public:
    virtual bool Export(const string& data)
    {
        cout << "ExportJson:   " << data << endl;
        return true;
    }
};

class ExportText : public IExport
{
public:
    virtual bool Export(const string& data)
    {
        cout << "ExportText:  " << data << endl;
        return true;
    }
};


class IExportFactory
{
public:
    virtual IExport* newExport() = 0;
};

class ExportXmlFactory : public IExportFactory
{
public:
    virtual IExport* newExport()
    {
        IExport* temp = new ExportXml();
        return temp;
    }
};

class ExportJsonFactory : public IExportFactory
{
public:
    virtual IExport* newExport()
    {
        IExport* temp = new ExportJson();
        return temp;
    }
};

class ExportTextFactory : public IExportFactory
{
public:
    virtual IExport* newExport()
    {
        IExport* temp = new ExportText();
        return temp;
    }
};

class ExportData
{
public:
    ExportData(IExportFactory* factory): _factory(factory) {}
    ~ExportData()
    {
        if (_factory)
        {
            delete _factory;
            _factory = nullptr;
        }
    }
    bool Export(const string& data)
    {
        IExport* e = _factory->newExport();
        e->Export(data);
        return 0;
    }

private:
    IExportFactory* _factory;
};

注解三:version1.3

#pragma once
using namespace std;
#include 
#include 

class IExport
{
public:
    virtual bool Export(const string& data) = 0;
    virtual~IExport() {};
};

class ExportXml : public IExport
{
public:
    virtual bool Export(const string& data)
    {
        cout << "ExportXml:  " << data << endl;
        return true;
    }
};

class ExportJson : public IExport
{
public:
    virtual bool Export(const string& data)
    {
        cout << "ExportJson:   " << data << endl;
        return true;
    }
};

class ExportText : public IExport
{
public:
    virtual bool Export(const string& data)
    {
        cout << "ExportText:  " << data << endl;
        return true;
    }
};


class IExportFactory
{
public:
    bool Export(const string& data)
    {
        if (_export == nullptr)
        {
            _export = newExport();
        }

        return _export->Export(data);
    }
private:
    IExport* _export;
protected:
    virtual IExport* newExport() = 0;
};

class ExportXmlFactory : public IExportFactory
{
protected:
    virtual IExport* newExport()
    {
        IExport* temp = new ExportXml();
        return temp;
    }
};

class ExportJsonFactory : public IExportFactory
{
protected:
    virtual IExport* newExport()
    {
        IExport* temp = new ExportJson();
        return temp;
    }
};

class ExportTextFactory : public IExportFactory
{
protected:
    virtual IExport* newExport()
    {
        IExport* temp = new ExportText();
        return temp;
    }
};



你可能感兴趣的:(面试必备,面试,经验分享)