• C++面试宝典设计模式之单例模式


    C++面试宝典设计模式篇之单例模式


    前言

    软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。设计模式是面试热门考点,掌握设计模式可以让你深入理解面向对象思想,使设计方案更加灵活,方便后期维护修改。

    一、设计模式之单例模式

    二、单例模式详细介绍

    2.1单例模式概念介绍

    单例模式属于创建型模式,这种模式涉及到一种单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一对象的方式。
    单例类的特征: 1.单例类最多只能有一个实例;
       2.单例类必须自己创建自己唯一的实例;
       3.单例类必须给所有其他的对象提供这一实例。

    2.2使用单例模式的目的和优缺点

    目的:使用单例类是为了保证某一个类仅有一个实例,并提供一个访问它的全局访问点。
        单例类主要解决了一个全局使用的类的频繁的创建与销毁。
        所以单例模式有以下几个优点: 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的 创建和销毁实例; 2、避免对资源的多重占用。
        缺点:单例模式有一个不好的地方就是:单例类没有接口,不能继承。

    2.3单例模式的使用场景

    当我们想在程序中控制实例数目,节约系统资源的时候,就可以考虑使用单例类。
    例如:1.频繁创建及销毁的对象,例如工具类;
    2.不变的对象;
    3.设备管理器,系统中可能有多个设备,但是只有一个设备管理器,用于管理设备驱动;
    4.数据池,用来缓存数据的数据结构,需要在一处写,多处读取或者多处写,多处读取;
    5.打印机,日志对象;

    2.4单例模式的定义方式

    定义一个单例类:

    (1)私有化构造函数,以防止外界创建单例类的对象。

    private Singleton()

    不需用拷贝和赋值,在单例模式中,始终只有一个对象

    (2)使用类的私有静态指针,变量指向类的唯一实例。(提供一个自身的静态私有成员变量,以指向类的实例;

    private static Singleton * uniqueInstance()

    (3)使用一个公有的静态方法获取该实例。

    public static Singleton * getInstance()

    2.5单例模式的实现方式

    懒汉式:故名思义,不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化。与之对应的是饿汉式单例。(注意,懒汉本身是线程不安全的)
    饿汉式:饿了肯定要饥不择食。所以在单例类定义的时候就进行实例化。(本身就是线程安全的)
    那如何选择懒汉和饿汉模式呢?
    特点与选择:

    懒汉:直接创建出类的实例化 因为上来就实例化一个对象,占用了内存,并不管主程序是否用到该类。在访问量较小时,采用懒汉实现。这是以时间换空间。

    饿汉:由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。

    三、单例模式代码示例

    3.1懒汉式代码示例

    /*懒汉式单例模式*/
    class Singleton_lazy{
    private:
        /*构造函数私有化,保证不在类的外部实例化*/
        Singleton_lazy(){cout<<"我是懒汉式构造函数"<<endl;}
    public:
        /*用户接口,在使用的时候创建一个类的实例化*/
        static Singleton_lazy* getInstance(){
            //判断pSingleton是否为NULL,如果为NULL,即判定需要实例化
            if (pSingleton==NULL){
                pSingleton=new Singleton_lazy;
            }
            return pSingleton;
        }
    private:
        static Singleton_lazy* pSingleton;    //静态类对象
    };
     
    //静态对象类外初始化
    Singleton_lazy* Singleton_lazy::pSingleton=NULL;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3.2饿汉式代码示例

    /*饿汉式单例模式*/
    class Singleton_hungry{
    private:
        Singleton_hungry(){cout<<"我是饿汉式构造函数"<<endl;}
    public:
        /*返回已经创建好的类实例*/
        static Singleton_hungry* getInstance(){
            return pSingleton;
        }
    private:
        static Singleton_hungry* pSingleton;
    };
     
    //类外初始化:直接创建出类的实例 
    Singleton_hungry* Singleton_hungry::pSingleton=new Singleton_hungry;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    如果想懒汉模式实现线程安全,则应该加锁

    3.3线程安全的懒汉式代码示例

    #include
    #include
    #include
    using namespace std;
    class Cperson
    {
    	private:
    		Cperson(){}
    		~Cperson(){}
    	private:
    		static Cperson* ps;
    		static pthread_mutex_t mutex;
    	public:
    		static Cperson* GetObject();
    		static void Destory(Cperson* p);
    
    };
    Cperson* Cperson::ps = 0;  
    pthread_mutex_t  Cperson::mutex = PTHREAD_MUTEX_INITIALIZER;
    
    Cperson* Cperson::GetObject() 
    {
    	if(ps == 0)
    	{
    		pthread_mutex_lock(&mutex);
    		if(ps  == 0)
    			ps = new Cperson;
    		pthread_mutex_unlock(&mutex);
    	}
    	return ps;
    }
    
    void Cperson::Destory(Cperson* p)
    {
    	if(p->ps)
    	{
    		delete p->ps;
    		p->ps == NULL;
    	}
    	pthread_mutex_destroy(&(p->mutex));
    }
    
    Cperson* p2;
    void* work(void *arg)
    {
    	p2 = Cperson::GetObject();
    	cout<<"work:"<<p2<<endl;
    	
    }
    int main()
    {
    	pthread_t tid = 0;
    	pthread_create(&tid,NULL,work,NULL);
    	//Cperson* p2 = Cperson::GetObject();
    	Cperson* p1 = Cperson::GetObject();
    	sleep(1);//防止主函数执行过快 线程函数还没来得及执行
    
    	cout<<"p1:"<<p1<<endl;
    	cout<<"p2:"<<p2<<endl;
    	Cperson::Destory(p1);
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    四、总结

    设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的的充分理解。
    正确使用设计模式有很多优点:
    1.可以提高程序员的思维能力、编程能力和设计能力。
    2.使面试程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。
    3.使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。
    今天博主分享的单例模式只是设计模式的一种,能在适当的场景使用合理的设计模式对于程序员的成长至关重要,后续博主会继续分享设计模式的学习经验。
    每日一语:虽然坚持自己的理想很难,但无论最后有没有实现都好,那种执着与信念,将是一生的财富,与大家共勉!

  • 相关阅读:
    漏洞-Alibaba Nacos derby 远程代码执行漏洞
    ssm+vue的图书管理系统(有报告)。Javaee项目,ssm vue前后端分离项目。
    css控制整个div下的所有元素中的文字放大缩小
    快速掌握 MyBatis 框架(二)
    核心实验11合集_hybrid接口特殊用法_ENSP
    【求教】老菜鸟遇到新问题,双bug欢迎有緣人答疑
    安防视频监控系统EasyCVR视频汇聚存储平台定制化开发:新增kafka配置
    【2024秋招】2023-10-9 同花顺后端笔试题
    transformer学习资料
    部署ik分词器
  • 原文地址:https://blog.csdn.net/wyhplus/article/details/126472434