首页 > 系统相关 >Linux C++ 060-设计模式之单例模式

Linux C++ 060-设计模式之单例模式

时间:2024-07-17 21:00:52浏览次数:16  
标签:060 CSingleton C++ 对象 single 实例 模式 单例 设计模式

Linux C++ 060-设计模式之单例模式

本节关键字:Linux、C++、设计模式、单例模式
相关库函数:

概念

单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。

动机

对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。

如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的模式动机。

构建方式

懒汉方式。指全局的单例实例在第一次被使用时构建。
饿汉方式。指全局的单例实例在类装载时构建。

要点

显然单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。

从具体实现角度来说,就是以下三点:一是单例模式的类只提供私有的构造函数,二是类定义中含有一个该类的静态私有对象,三是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。

在下面的对象图中,有一个"单例对象",而"客户甲"、“客户乙” 和"客户丙"是单例对象的三个客户对象。可以看到,所有的客户对象共享一个单例对象。而且从单例对象到自身的连接线可以看出,单例对象持有对自己的引用。

一些资源管理器常常设计成单例模式。

在计算机系统中,需要管理的资源包括软件外部资源,譬如每台计算机可以有若干个打印机,但只能有一个Printer Spooler, 以避免两个打印作业同时输出到打印机中。每台计算机可以有若干传真卡,但是只应该有一个软件负责管理传真卡,以避免出现两份传真作业同时传到传真卡中的情况。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。

需要管理的资源包括软件内部资源,譬如,大多数的软件都有一个(甚至多个)属性(properties)文件存放系统配置。这样的系统应当由一个对象来管理一个属性文件。

需要管理的软件内部资源也包括譬如负责记录网站来访人数的部件,记录软件系统内部事件、出错信息的部件,或是对系统的表现进行检查的部件等。这些部件都必须集中管理,不可整出多头。

这些资源管理器构件必须只有一个实例,这是其一;它们必须自行初始化,这是其二;允许整个系统访问自己这是其三。因此,它们都满足单例模式的条件,是单例模式的应用。

优缺点

优点

1、实例控制:单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。

2、灵活性:因为类控制了实例化过程,所以类可以灵活更改实例化过程。

缺点

1、开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。

2、可能的开发混淆:使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。

3、对象生存期:不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。

代码示例

// 说明:在初始化类中的静态成员(该类的唯一一个对象)时,创建对象。
// 总结:
//        类中的构造函数是private类型,该类的实例对象是静态指针类型
//        访问该类的全局访问点是类中public类型的静态函数,函数的返回值是该类的指针类型
//        在类的外部需要对类中定义的静态成员(该类的静态指针类型对象)进行初始化,初始化形式:类型名 类名 作用域运算符 变量名 等于 初始值;(懒汉模式:初始值为指向实例对象的指针)
//        客户端只能通过类的静态成员函数实例化一个对象
// 
// 单例模式 - 饿汉单例模式
// 饿汉式单例模式,顾名思义就是程序启动时就实例了该现象,并没有推迟到第一次使用该对象再进行实例化;如果运行过程中没有使用到,该实例对象就被浪费掉了
// 饿汉单例模式中,单例对象定义成了一个static静态对象,它是在程序启动时,main函数运行之前就初始化好的,因此不存在线程安全问题,可以放心在多线程环境中使用
class CSingleton_1 {
public:
    static CSingleton_1* getInstance() {
        return &single;
    }
private:
    static CSingleton_1 single;
    CSingleton_1() {}
    ~CSingleton_1() {}
    CSingleton_1(const CSingleton_1&) {}
};
CSingleton_1 CSingleton_1::single;

// 单例模式 - 懒汉单例模式
// 懒汉单例模式,顾名思义,就是对象的实例化,延迟到第一次使用它的时候
// 懒汉单例模式中,getInstance()是个不可重入函数,也就是它在多线程环境中执行,会出现竞态条件问题,因此需要考虑加锁
class CSingleton_2 {
public:
    static CSingleton_2* getInstance() {
        // 获取互斥锁

        if (single == NULL) {
            single = new CSingleton_2();
        }
        return single;
    }
private:
    static CSingleton_2* single;
    CSingleton_2() {}
    ~CSingleton_2() {}
    CSingleton_2(const CSingleton_2&) {}

    // 注意如果没有下面的释放资源类,在main函数中将手动释放资源
    class CRelease {
    public:
        ~CRelease() {
            if (single)
                delete single;
        }
    };
    static CRelease release;

    // 定义线程间的互斥锁
    static pthread_mutex_t mutex;
};
CSingleton_2* CSingleton_2::single = NULL;
CSingleton_2::CRelease CSingleton_2::release;
// 互斥锁初始化
pthread_mutex_t CSingleton_2::mutex = PTHREAD_MUTEX_INITIALIZER;

标签:060,CSingleton,C++,对象,single,实例,模式,单例,设计模式
From: https://blog.csdn.net/qq_45157350/article/details/135869815

相关文章

  • C++ 基础 - 3 - 数据类型
    简言什么是数据类型?数据类型(DataTypes)是变量或函数返回值的属性,它们决定了变量可以存储哪种类型的数据,以及这些数据如何被解释和存储在计算机的内存中。C++是一种静态类型语言,这意味着每个变量都必须在使用前声明其类型。C++提供了丰富的数据类型,可以分为几大类:基本......
  • C++ 基础 - 2 - 变量常量
    简言什么是变量与常量在计算机编程中,变量是存储数据的一种容器。它可以用于存储各种类型的数据,如整数、浮点数、字符串等。变量的值可以随时改变。常量与变量相反,常量是一个固定的值,它在程序运行期间是不会改变的。常量在程序中起到类似变量的作用,但其值是固定的,不能被......
  • C++学习第一天
    CPP的学习day11.VisualStudio的学习安装跳过……1.创建项目选择创建新项目因为是学习,选择第二个控制台应用分配好后点击创建等一会儿就创建好了……先修改设置:右击选择属性然后改为如下图2.CPP的表达式概念表达式就是运算符和操作数的序列,指定一项计算,表达式的求......
  • c++中结构体与类的区别
    在C++中,结构体(struct)与类(class)在功能上非常相似,实际上他们之间的主要区别在于默认的访问权限和继承方式。下面详细解释这两种类型的区别:结构体与类最大的不同就在于访问权限默认访问权限结构体(struct):默认的成员访问权限是公开的(public)。这意味着,除非显式地指定访问......
  • C++竞赛优化技巧与考场实用技巧
    在洛谷观看更加简约哦~:一键直达距离2024CSP/NOIP已经不远了,在这里,我便分享一下我总结出来的竞赛优化技巧时间优化算法/数据结构优化在处理一些问题,我们可以采用更高效的算法/数据结构来代替低效的算法/数据结构。例如,你需要多次求一段区间的和时,一般会采用循环直接......
  • 模板设计模式
    模板模式(TemplatePattern)是一种行为设计模式,它在一个方法中定义一个操作的骨架,而将一些步骤的实现延迟到子类中。模板方法模式使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。模板模式的组成部分抽象类(AbstractClass):定义算法的骨架,并包含一个模板方法。......
  • 设计模式之抽象工厂模式(学习笔记)
    定义抽象工厂模式是一种创建型设计模式,它提供一个接口,用于创建一系列相关或依赖的对象,而无需指定它们的具体类。抽象工厂模式将对象的创建过程抽象化,允许子类通过实现具体工厂类来定制对象的创建。为什么使用抽象工厂模式产品族的一致性抽象工厂模式确保同一产品族中的对......
  • 设计模式之代理模式
    定义代理模式(ProxyPattern)是软件工程中的一种设计模式,它属于结构型模式,用于在不直接访问实际对象的情况下,通过一个或多个代理对象来间接访问某个对象或执行某些操作。目的这种模式的主要目的是:控制访问:代理可以在访问真实对象之前或之后添加额外的操作,如权限检查、延迟初始......
  • 2024年华为OD机试真题-图像物体的边界-C++-OD统一考试(C卷D卷)
     2024年OD统一考试(D卷)完整题库:华为OD机试2024年最新题库(Python、JAVA、C++合集)题目描述:给定一个二维数组M行N列,二维数组里的数字代表图片的像素,为了简化问题,仅包含像素1和5两种像素,每种像素代表一个物体,2个物体相邻的格子为边界,求像素1代表的物体的边界个数。像素1代表的......
  • Visual Studio 2022下载安装教程c++
    文章目录VisualStudio安装教程一、官网下载二、安装三、配置四、VisualStudio2022使用教程VisualStudio安装教程一、官网下载下载地址:https://visualstudio.microsoft.com/zh-hans/downloads/二、安装要是个人学习的活就下载社区版下载完成后是一个安......