【软件设计师中级】设计模式之单例模式学习笔记(c++)

【软件设计师中级】设计模式之单例模式学习笔记(c++),第1张

本文适合新手和小白 本例子使用的饿汉模式

目录

1、Singleton

(1)意图

(2)结构

(3)适用性

2、根据UML编写代码

(1)关键字static

(2)类外定义

(3)利用private

(4)唯一性

3、完整代码编写

1、Singleton (1)意图

保证一个类只有一个实例,并提供一个访问它的全局访问点

(2)结构
单例模式结构图

备注:根据《软件设计师教程》第五版第383页临摹

其中Singleton指定一个Instance *** 作,允许客户访问唯一个实例,Instance是一个类 *** 作,可能负责创建它自己的唯一实例。

(3)适用性

singleton模式适用于:

当类只有一个实例而客户可以从一个总所周知的访问点访问它时。

当这个唯一实例应该是通过子类可扩展的,并且可恶无须更改代码就能使用一个扩展的实例时。

2、根据UML编写代码

单例模式的类图非常简,只有一个类,2个属性、3 *** 作,其中instancel用于负责返回一个唯一实例(uniqueinstance),由于只有一个类我们无需先根据父子类继承、依赖关系等先写一个伪代码,在根据逻辑逐渐完善代码,需要特别注意的是,在其他的设计模式中,我们实例化产生一个对象的时候,往往会做这样的 *** 作:

  父类 *对象名= new 子类名 或者 类名 *对象名=new 类名

    如果我们按照上述代码 *** 作,假如我们有一个类A,我们做如下 *** 作: A *a=new A A*b=new B,a和b是完全独立的两个实例化对象,如果我们直接采用这种方式,无法实现单例模式构建唯一用例用意。我们需要做到是即便我们在 *** 作中反复使用了 A *a=new A    A*b=new B的 *** 作,也要让a=b,要做到这几点我们需要知道以下知识点:

  (1)关键字static

     局部变量  int a 他的生命周期在于它的作用域,超出范围后a这个变量会被销毁,若在 int a前加上static变成 static int a 就变成了局部静态变量,单例模式需要利用下特点:

       1、 存储在静态存储区(存储在静态存储区的变量,如果不显式地对其进行初始化,系统会将其初始化为0),在程序执行期间,对应的存储空间不会释放,一直到程序结束才会释放。

      2、存储在静态存储区的静态变量,他所在函数生命周期结束后,它占用的存储空间也不会释放,但其他函数不能引用该局部静态变量。当下一次调用该函数时,不会再次对该局部静态变量进行初始化,它的值是上一次函数调用结束时的值。

      3、 在类中声明static变量或者函数时,初始化时使用作用域运算符(::)来标明它所属类,静态成员是类的成员(所有对象中共享的成员),而不是某一个对象的成员。

   4、静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定的对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以 *** 作它。

备注:以上4点 根据 CSDN博主「舒泱」的原创文章进行整理 ,原文链接:https://blog.csdn.net/weixin_43222324/article/details/106999558

      综上我们使用粗劣的代码进行一个下 *** 作:

#include
using namespace std;
class A{
  private:
      
   public:
      A(){
      cout<<"hello"<

运行结果为 c++

我们可以看出即便我们没有对A进行实例化也可以使用A类中的静态变量print。

(2)类外定义

  我们可以在类外进行一些 *** 作,我们直接上代码:

#include
using namespace std;
class A{
  private:
      
   public:
      A(){
      cout<<"hello"<

输出结果为:hello

                      c++

(3)利用private

为了确保单例,我们必然要保证A不能被随意实例化,所以我们可以利用private权限的特点将构造函数从public转移到private中,我们直接上代码看看效果:

#include
using namespace std;
class A{
  private:
        A(){
      cout<<"hello"<

使用g++编译,程序报错报错内容为: 错误: ‘A::A()’是私有的 。

    根据这错误提示我们无法直接用A *a来接受new A 创建的实例。所以如果我在A类中创建一个  static A*aa就可以在没有实例的化的前提下,利用static性质存储new A产生的实例。然后通过在public中添加一个函数再将这个实例调出来使用实现对类A的 *** 作。

#include
using namespace std;
class A{
  private:
        A(){
      cout<<"hello"<print();利用public定义一个接口将aa(储存的实例对象)调用出来实现对类A的 *** 作
    return 0;
}

输出结果 hello

                 c++

这里实际上我们就已经完成了单例模式(饿汉)绝大部分代码。

(4)唯一性

      由于我们使用了static,根据静态函数的特征为确保唯一性我们需要做到以下4点:

       一、他们的结果存在静态区结果不会被销毁;

       二、不会再次对该局部静态变量进行初始化,它的值是上一次函数调用结束时的值。

      三、静态数据成员在全局数据区分配内存,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以 *** 作它。

     四、私有化构建函数让 *** 作员无法在其他地方创建对象

  相关代码演示我们在完整代码中演示


3、完整代码编写

       结合上述知识点和UML图的要求我们编写代码如下:

#include
using namespace std;
class Singleton{
    private:
        Singleton(){//定义在private中确保不能被随意实例化
            singletondata=100;
        }
        ~Singleton(){}
        static  Singleton *uniqueinstance;//用于存储实例
        int singletondata;
    public:
        void  getsingletondata(){
            cout<singletondata++;
        }
        static Singleton* Instance();//一个返回uniquelinstance(唯一实例)接口,确保唯一性
};
Singleton*Singleton::uniqueinstance=new Singleton();//在进入main函数前将其实例化
Singleton* Singleton::Instance(){//将实例返回,在main函数中去获取确保唯一性。
    return uniqueinstance;//饿汉模式确保多线程使用的安全
}
int main(){

    Singleton *a=Singleton::Instance();
    a->getsingletondata();//100
    a->SingletonOperation();//+1
    a->getsingletondata();//101
    cout<<"-----------------------------"<getsingletondata();//101 与a保持一致
    return 0;
}

在进入main函数前,Singleton*Singleton::uniqueinstance=new Singleton() 这段代码将产生的实例存入在uniqueinstan之中,因为uniqueinstan是静态变量,她的值会一直保存 ,a和b通过Instance都是从保存在静态区的uniqueinstan去获取实例,所以a和b获得是同一个实例,故a在执行了SinletonOperation这个自增长的 *** 作后(getsingletondata从100变为101),b通过getsingletondata得到的数字也是101。

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

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

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

发表评论

登录后才能评论

评论列表(0条)