单例模式C++实现和观察者模式C++实现

news/2024/12/19 4:58:52/

目录

1、单例模式介绍

2、单例代码实现

2.1  static介绍

2.2 C++中static的三种用法:

(1)静态局部变量

(2)静态成员变量

(3)静态成员函数

3、观察者模式介绍

4、观察者代码实现


1、单例模式介绍

      单例模式是属于设计模式中的创建型模式分类(将对象的创建和使用相互分离)。

      单例模式使用的场景是:在一个进程中,只有一个实例对象。该实例构造函数一般声明为私有类,类外不可访问。通过提供访问实例对象的公共函数来访问该实例对象。

      单例模式优点:保证整个程序中只有一个实例类,既保证了数据的唯一性,又节省了空间。

单例的实现方式有:

(1)懒汉式。              (使用时进行实例化。存在线程安全问题)

(2)静态局部变量。    (使用时进行实例化。不存在线程安全问题)

(3)饿汉式。                (单例类创建的时候进行实例化。不存在线程安全问题)

2、单例代码实现

推荐使用静态局部变量实现单例,具体的代码如下:

#include <iostream>class SingletInstance
{
public:static SingletInstance* getInstance(){static SingletInstance ins;return &ins;}
private:SingletInstance(){std::cout << "SingletInstance Constructot " << std::endl;};
};int main()
{std::cout << "this addr is  " << SingletInstance::getInstance() << std::endl;std::cout << "this addr is " << SingletInstance::getInstance() << std::endl;return 0;
}

代码运行结果如下:

单例的各种实现方式可参考下面链接:

总结C++单例模式_c++ proto类需要自己释放吗_发如雪Jay的博客-CSDN博客

2.1  static介绍

        C++内存分区可大致分为:栈、堆、全局数据区(静态区)、代码区,staitc修饰的内容属的于全局数据区(静态区),全局数据区中存在的变量包括:全局变量和静态变量存储,生成周期在程序结束时释放。

2.2 C++中static的三种用法:

(1)静态局部变量

      定义:使用static修饰类型的变量,如static int a。生命周期为程序运行周期。

      优点:静态局部变量的作用域外部不可访问,具有较好的安全性。

       注意:只初始化一次,若不赋值,则自动赋值为0,下一次进入该函数时,会自动忽略初始化语句。

代码如下:

void func()
{static int a = 10;a++;std::cout << "a " << a << std::endl;
}int main()
{int cnt = 1;while(cnt <= 3){func();cnt++;}return 0;
}

运行结果如下:

(2)静态成员变量

定义:使用static修饰的类成员变量,生命周期为程序运行周期。 

注意:每个类的对象的静态成员变量指向的是同一个块地址区域,即数据内容和地址一样。

必须在类对象使用前初始化。

代码如下:

#include <iostream>class A
{
public:static int a;
};int A::a = 10; //必须使用前初始化!
int main()
{std::cout << "A::a  is " << A::a <<",addr is " <<  &(A::a) << std::endl;/ 下面访问静态成员变量的方法不使用,只为了说明,一般使用A::a访问静态成员变量。 //A obj1;A obj2;A obj3;std::cout << "A::a  is " << obj1.a << ",addr is " << &(obj1.a) <<std::endl;std::cout << "A::a  is " << obj2.a << ",addr is " << &(obj2.a) <<std::endl;std::cout << "A::a  is " << obj3.a << ",addr is " << &(obj3.a) <<std::endl;//return 0;
}

运行结果如下:

(3)静态成员函数

  定义:在成员函数前面加上static修饰符,如:static void fun(){};

  访问:用类名::函数名进行访问

 静态成员函数与非静态成员函数区别:非静态成员函数可以任意地访问静态成员函数和静态数据 成员,静态成员函数不能访问非静态成员函数和非静态数据成员。

3、观察者模式介绍

 观察者模式属于设计模式中的行为型模式分类(关注对象的行为或者交互方面的内容)。

观察者模式使用场景是 描述多个观察者(Observer)订阅一个被观察者的对象状态;当被观察者状态变化时,被观察者会通知所有订阅的观察者对象,让其接收取到状态变化信息。

应用:Qt框架中数据间的通信机制是信号槽,信号槽机制就是观察者模式_百度百科 (baidu.com)应用的体现。

观察者模式也被称为发布者-订阅模式。观察者模式是对象间一对多的关系描述,类似广播。

4、观察者代码实现

代码设计的观察对象如下:

(1)定义一个抽象的被观察者(AbsTarget)类,该类有订阅、取消订阅、通知属性变化、设置数据的接口。

(2)被观察对象(Target1)继承于AbsTarget,对应的观察者对象有Observer1、Observer2。

(3)被观察对象(Target2)继承于AbsTarget,对应的观察者对象Observer3。

(4) 定义一个抽象的观察者(AbsObserver)类,该类有接收数据变化的接口,该接口为了应对不同的数据类型,接收的数据类型定义为void*。

(5)观察者1(Observer1)继承于AbsObserver类;观察者2(Observer2)继承于AbsObserver类,Observer1和Observer2接收数据变化的数据结构为同一种。

(6)观察者3(Observer3)继承于AbsObserver类,Observer3接收的数据结构为一种。

具体代码实现如下:

#include <iostream>
#include <list>
#include <string>
struct Data1
{int n1;float f1;
};struct Data2
{int n1;std::string strname;
};
//观察者
class AbsObserver
{
public:AbsObserver()=default;virtual ~AbsObserver(){};virtual void receiveData(void* pThis)=0;    //使用void*来适应不同的数据类型
};//具体观察者1
class Observer1:public AbsObserver
{
public:Observer1()=default;~Observer1(){};virtual void receiveData(void* pThis)override{Data1* data1 = (Data1*)pThis;std::cout << "  Observer1 receive ";std::cout << "f1: " <<  data1->f1 <<  ", n1: " <<data1->n1 << std::endl;}
};//具体观察者2
class Observer2:public AbsObserver
{
public:Observer2()=default;~Observer2(){};virtual void receiveData(void* pThis)override{Data1* data1 = (Data1*)pThis;std::cout << "  Observer2 receive ";std::cout << "f1: " <<  data1->f1 <<  ", n1: " <<data1->n1 << std::endl;}
};class Observer3:public AbsObserver
{
public:Observer3()=default;~Observer3(){};virtual void receiveData(void* pThis)override{Data2* data1 = (Data2*)pThis;std::cout << "  Observer3 receive ";std::cout << "strname: " <<  data1->strname <<  ", n1: " <<data1->n1 << std::endl;}
};//被观察目标
class AbsTarget{
public:AbsTarget()=default;virtual ~AbsTarget(){std::cout << "~AbsTarget" << std::endl;};virtual void Attach(AbsObserver* obj)=0;virtual void Detach(AbsObserver* obj)=0;virtual void NotifyData()=0;virtual void setData(void* data)=0;};//具体被观察目标类型1
class Target1:public AbsTarget
{
public:Target1()=default;virtual ~Target1(){std::cout << "~Target1" << std::endl;if(m_pObservers.size() >0){m_pObservers.clear();std::cout << "Target1 clear Data" << std::endl;}};virtual void Attach(AbsObserver* obj)override{m_pObservers.push_back(obj);};virtual void Detach(AbsObserver* obj)override{m_pObservers.remove(obj);};virtual void NotifyData()override{for(auto it:m_pObservers){it->receiveData(&m_data1);}}void setData(void* data)override{Data1* tmp = (Data1*)data;m_data1.f1 =tmp->f1;m_data1.n1 =tmp->n1;std::cout << "Target1 NotifyData************" << std::endl;NotifyData();}
private:std::list<AbsObserver*>m_pObservers;Data1 m_data1;
};//具体被观察目标类型2
class Target2:public AbsTarget
{
public:Target2()=default;virtual ~Target2(){std::cout << "~Target2" << std::endl;if(m_pObservers.size() >0){m_pObservers.clear();std::cout << "Target2 clear Data" << std::endl;}};virtual void Attach(AbsObserver* obj)override{m_pObservers.push_back(obj);};virtual void Detach(AbsObserver* obj)override{m_pObservers.remove(obj);};virtual void NotifyData()override{for(auto it:m_pObservers){it->receiveData(&m_data1);}}void setData(void* data)override{Data2* tmp = (Data2*)data;m_data1.strname =tmp->strname;m_data1.n1 =tmp->n1;std::cout << "Target2 NotifyData************" << std::endl;NotifyData();}
private:std::list<AbsObserver*>m_pObservers;Data2 m_data1;
};void UseTarget1()
{AbsTarget *pTarger1 = new Target1();AbsObserver* pObserve1= new Observer1();pTarger1->Attach(pObserve1);AbsObserver* pObserve2= new Observer2();pTarger1->Attach(pObserve2);Data1 tmp;tmp.f1 = 30.06;tmp.n1 = 60;pTarger1->setData(&tmp);pTarger1->Detach(pObserve1);pTarger1->setData(&tmp);pTarger1->Detach(pObserve2);delete  pTarger1;pTarger1 = nullptr;delete  pObserve1;pObserve1 = nullptr;delete  pObserve2;pObserve2 = nullptr;
}void UseTarget2()
{AbsTarget *pTarger2 = new Target2();AbsObserver* pObserve3= new Observer3();pTarger2->Attach(pObserve3);Data2 tmp;tmp.strname = "hello";tmp.n1 = 60;pTarger2->setData(&tmp);pTarger2->Detach(pObserve3);delete  pTarger2;pTarger2 = nullptr;delete  pObserve3;pObserve3 = nullptr;}
int main()
{std::cout << "*********** Use Target1, Observer1, Observer2 ***********" << std::endl;UseTarget1();std::cout << "\n*********** Use Target2, Observer3 ***********" << std::endl;UseTarget2();return 0;
}

程序运行结果如下:

 关于观察者模式介绍也可参考:

C++行为型模式-实现观察者模式_观察者模式c++实现_herryone123的博客-CSDN博客

附加:

1、设计模式介绍和分类可参考:

C++设计模式介绍与分类_夜雨听萧瑟的博客-CSDN博客

2、static的用法可参考:

c++中static的用法详解_c++中static的作用和用法_「已注销」的博客-CSDN博客

对C语言 static作用——修饰 变量(全局变量/局部变量)、函数_c语言static修饰的局部变量_杰儿__er的博客-CSDN博客

3、对信号槽机制感兴趣的可参考链接:

信号槽机制_夜雨听萧瑟的博客-CSDN博客


http://www.ppmy.cn/news/209241.html

相关文章

如何在 Python 中设置请求的最大重试次数

文章目录 Python中设置请求max_retries的错误&#xff0c;的原因和解决方案在 Python 中摆脱请求的 Set max_retries 的技巧 本篇文章介绍了为什么我们会收到错误消息&#xff0c;指出超出了最大重试次数&#xff0c;以及我们如何在 Python 中为请求设置 max_retries。 如果服务…

什么镜头最适合拍风景_风景用什么镜头好

展开全部 外出旅游的复时候的携制带镜头需要考虑的因素还bai是比较多du的&#xff0c;一般来说要考虑zhi到拍摄题材dao、背负重量等综合因素来选择&#xff0c;下面我就来和您说明一下我如果自己外出旅游的话&#xff0c;会选择怎样的镜头拍摄风光~ 16-35mm F4/2.8 超广角变焦镜…

佳能85mmF#1.4L IS USM镜头构造

本镜头感觉可以看到双高斯镜头的影子&#xff0c;焦距和大光圈让镜头保持良好的虚化效果。主要用于婚纱摄影&#xff0c;值得一提的是为了控制间隔&#xff0c;机械件以0.1mm的间隔进行缩减&#xff0c;从中可以看到结构件设计的影子&#xff1b;为了减小镜头的重量&#xff0c…

哪些镜头焦外表现最好

http://www.zhihu.com/question/26751916 著作权归作者所有。 商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 作者&#xff1a;Thomas Schuss 链接&#xff1a;http://www.zhihu.com/question/26751916/answer/38691416 来源&#xff1a;知乎 先说结论&#…

相机选型与远心镜头选型

相机选型&#xff1a; 1、确定精度需求&#xff1a; 例如我需要的精度为0.1mm&#xff0c;那么在选择相机时分辨率时一般要高于这个精度&#xff0c;那么我这里按照1/5 计算&#xff0c;也就是0.02mm&#xff1b; 再根据视野需求来计算相机分辨率&#xff1a;例如我的视野需求…

18135usm_更快更安静佳能18-135mmUSM镜头解析

在135mm画幅相机上&#xff0c;24-70mm或是24-105mm等这些标准变焦镜头由于具备能广能长的焦段而受到很多用户的喜爱&#xff0c;而在APS-C画幅相机上自然也是如此&#xff0c;诸如18-55mm、18-135mm这些镜头往往更容易满足人们“一镜走天下”的需求。说起18-135mm焦段的镜头&a…

知识付费海哥:不理解这一点,你永远无法“知识变现”

哈喽&#xff0c;大家好&#xff0c;我是海哥&#xff0c;知识付费变现创业教练&#xff0c;教育公司培训总监&#xff0c;从事知识付费变现咨询10年&#xff0c;已助力3000人实现知识付费变现。 知识变现&#xff0c;是当前很热门的一个词。 由罗振宇率领的得到系老师&#…

18135usm_佳能PZ-E1+EF-S 18-135mm f/3.5-5.6 IS USM镜头 小型工作室的利器

EF-S 18-135mm f/3.5-5.6 IS USM 在大神眼里据对是属于狗头系列的 哈哈哈 但是这货如果搭配佳能的 PZ-E1 在配合佳能80D 那绝对是小型视频工作室的首选 &#xff01;&#xff01;&#xff01; mxcpTB2rqUOg80kpuFjSsppXXcGTXXa_!!104284319.jpg (156.5 KB, 下载次数: 1) 2017-…