【C++】单例模式和观察者模式

【C++】单例模式和观察者模式,第1张

单例模式(创建型)

创建型模式:提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象

确保系统中某个类只有唯一一个实例,当这个唯一实例创建成功之后,我们无法再创建一个同类型的其他对象,所有的 *** 作都只能基于这个唯一实例

比如日志模块,数据库模块,任务管理器

饿汉式单例模式

  • 还没有获取实例对象,实例对象就已经产生了,饿汉式是线程安全的
  • 优点:程序加载时就进行实例化,之后的 *** 作效率会很高。

  • 缺点: 由于程序加载时就进行实例化,如果后续不对此类进行任何 *** 作,就会导致内存的浪费
//饿汉式单例:没调用获取单例对象的接口,单例对象就已经产生了
class Singleton
{
public:
    static Singleton* getInstance()					//3 定义获取唯一实例的接口方法
    {
        return &instance;
	}
private:
    static Singleton instance;						//2 定义一个唯一的类的实例对象
private:
    Singleton() {}						 			//1 构造函数私有化
    Singleton(const Singleton&) = delete;			//1 删除拷贝构造
    Singleton& operator=(const Singleton&) = delete;//1 删除赋值重载
    
};
Singleton Singleton::instance;  //类的static成员要在类外初始化,不赋初值则为编译器默认值

static成员要在类外初始化。

为什么?

因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,会导致每个对象都包含该静态成员,这是矛盾的。

懒汉式单例模式

  • 直到第一次获取唯一实例的时候,才产生实例
  • 优点: 在第一次调用的时候才进行实例化。

  • 缺点: 当多个线程同时进入到 if(instance == nullptr) {…} 时,会创建多个对象。

//懒汉式单例,将对象的实例化延迟到第一次调用的时候
class Singleton
{
public:
    static Singleton* getInstance()					//3 定义获取唯一实例的接口方法
    {
        if(instance == nullptr)
        {
            instance = new Singleton();
        }
        return instance;
	}
private:
    static Singleton *instance;						//2 定义一个唯一的类的实例对象
private:
    Singleton() {}						 			//1 构造函数私有化
    Singleton(const Singleton&) = delete;			//1 删除拷贝构造
    Singleton& operator=(const Singleton&) = delete;//1 删除赋值重载
    
};
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;  //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 
#include 
#include 
using namespace std;

//观察者抽象类
class Observer 
{
public:
	//处理消息的接口
	virtual void handle(int msgid) = 0;  
};

//第1个观察者实例
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;
		}
	}
};

//第2个观察者实例
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;
		}
	}
};

//第3个观察者实例
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);  //往msgid对应的观察者链表中插入obser,这句等价于下面注释中的
		/*auto it = _subMap.find(msgid);
		if (it != _subMap.end())
		{
			it->second.push_back(obser);
		}
		else
		{
			list lis;
			lis.push_back(obser);
			_subMap.insert({ msgid, lis });
		}*/
	}

	//通知观察者
	void dispatch(int msgid)
	{
		auto it = _subMap.find(msgid);
		if (it != _subMap.end())
		{
			for (Observer* pObser : it->second)  //遍历list
			{
				pObser->handle(msgid);
			}
		}
		else
		{
			cout << "没有观察者对该消息感兴趣" << endl;
		}
	}
private:
	unordered_map<int, list<Observer*>> _subMap;//msgid - 对该msgid感兴趣的观察者们
};

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);
	}
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/674562.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-19
下一篇 2022-04-19

发表评论

登录后才能评论

评论列表(0条)

保存