单例模式(创建型)
创建型模式:提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象
确保系统中某个类只有唯一一个实例,当这个唯一实例创建成功之后,我们无法再创建一个同类型的其他对象,所有的操作都只能基于这个唯一实例
比如日志模块,数据库模块,任务管理器
饿汉式单例模式
- 还没有获取实例对象,实例对象就已经产生了,饿汉式是线程安全的
- 优点:程序加载时就进行实例化,之后的操作效率会很高。
- 缺点: 由于程序加载时就进行实例化,如果后续不对此类进行任何操作,就会导致内存的浪费
class Singleton
{
public:
static Singleton* getInstance()
{
return &instance;
}
private:
static Singleton instance;
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
Singleton Singleton::instance;
static成员要在类外初始化。为什么?
因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,会导致每个对象都包含该静态成员,这是矛盾的。
懒汉式单例模式
- 直到第一次获取唯一实例的时候,才产生实例
- 优点: 在第一次调用的时候才进行实例化。
- 缺点: 当多个线程同时进入到 if(instance == nullptr) {…} 时,会创建多个对象。
class Singleton
{
public:
static Singleton* getInstance()
{
if(instance == nullptr)
{
instance = new Singleton();
}
return instance;
}
private:
static Singleton *instance;
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
Singleton* Singleton::instance = nullptr;
加互斥量,保证getInstance多线程环境是安全的
std::mutex mtx;
class Singleton
{
public:
static Singleton* getInstance()
{
if(instance == nullptr)
{
lock_guard<std::mutex> guard(mtx);
if(instance == nullptr)
{
instance = new Singleton();
}
}
return instance;
}
private:
static Singleton *volatile instance;
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
Singleton*volatile Singleton::instance = nullptr;
懒汉式单例代码2:
std::mutex mtx;
class Singleton
{
public:
static Singleton* getInstance()
{
static Singleton instance;
return &instance;
}
private:
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
观察者模式(行为型)
行为型模式主要关注的是对象之间的通信
观察者模式别名:发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式
主要关注的是对象的一对多的关系,也就是多个对象都依赖一个对象,当该对象的状态发生改变时,其他对象都能够接收到相应的通知
例如:通过一组数据(数据对象)可以绘制曲线图(对象1)、柱状图(对象2)、圆饼图(对象3),当数据对象发生改变时,对象123都要及时收到通知,图形上做出相应的改变
Observer1,Observer2,Observer3
Subject(主题)有更改,应该及时通知相应的观察者,去处理相应的事件
#include <iostream>
#include <unordered_map>
#include <list>
using namespace std;
class Observer
{
public:
virtual void handle(int msgid) = 0;
};
class Observer1 : public Observer
{
public:
void handle(int msgid)
{
switch (msgid)
{
case 1:
cout << "Observer1 recv msg1!" << endl;
break;
default:
cout << "Observer1 recv unknown msg!" << endl;
break;
}
}
};
class Observer2 : public Observer
{
public:
void handle(int msgid)
{
switch (msgid)
{
case 2:
cout << "Observer2 recv msg2!" << endl;
break;
default:
cout << "Observer2 recv unknown msg!" << endl;
break;
}
}
};
class Observer3 : public Observer
{
public:
void handle(int msgid)
{
switch (msgid)
{
case 3:
cout << "Observer3 recv msg3!" << endl;
break;
default:
cout << "Observer3 recv unknown msg!" << endl;
break;
}
}
};
class Subject
{
public:
void addObserver(Observer* obser, int msgid)
{
_subMap[msgid].push_back(obser);
}
void dispatch(int msgid)
{
auto it = _subMap.find(msgid);
if (it != _subMap.end())
{
for (Observer* pObser : it->second)
{
pObser->handle(msgid);
}
}
else
{
cout << "没有观察者对该消息感兴趣" << endl;
}
}
private:
unordered_map<int, list<Observer*>> _subMap;
};
int main()
{
Subject subject;
Observer *p1 = new Observer1();
Observer *p2 = new Observer2();
Observer *p3 = new Observer3();
subject.addObserver(p1, 1);
subject.addObserver(p2, 2);
subject.addObserver(p3, 3);
int msgid = 0;
while (1)
{
cout << "消息id:" ;
cin >> msgid;
if (msgid == -1)
break;
subject.dispatch(msgid);
}
}
|