以下详细介绍几种常见的设计模式: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;
}
};