单例模式(C++描述)+可以创建任何类的单例模式(template)

本文深入探讨C++中的单例模式,包括懒汉模式和饿汉模式的实现及线程安全性讨论。并通过模板方式实现了通用的单例模式,适用于任何类的单例创建。

单例模式(C++描述)+可以创建任何类的单例模式(template)


一.单例模式总结:

假设公司只有一台打印机,学校只有一个校长,多个线程处理同一个文件,我们在new对象时,想要避免这些只有一个的变量出现多个,此时就需要用到单例模式。

用法总结:
1.只能通过调用类中的函数来创建对象,其他方法均不行。
2.实例化的对象必须是唯一的,如果还有用户申请返回对象,返回的对象其实是同一个实例化的对象。

优点:
1.防止堆资源被浪费,降低了内存空间的开销;
2.作为唯一的公共资源防止被同时使用。

二.关于单例模式的问题:

1.构造函数与析构函数为什么要放在private区域中?
这样就只能通过getInstance和destory两个函数来操纵构造和析构函数!

2.getInstance为什么要加上static?
因为要想用类名直接调用成员函数,成员函数必须是static修饰的才行!

3.pInstance为什么要用static修饰?
因为操作pInstance的getInstance函数是用static修饰的,所以pInstance也只能加上staic修饰(static函数只能操作static成员变量!)

4.为什么在类外还要对pInstance进行定义?
因为在类中pInstance只是进行了申明,光是申明无法进行操作,必须加上定义才行!


1.懒汉模式(lazy loading)

Singleton *Singleton::pInstance = NULL;这个语句表明了是懒汉模式,即pInstance没有在一开始就申请对象。这样是线程不安全的状态(因为可能多个线程同时申请对象),则需要加锁。

class Singleton
{
public:
    //函数这里为什么要加上static?因为要想用类名直接调用成员函数,成员函数必须是static修饰的才行!
    static Singleton *getInstance()
    {
        if (pInstance == NULL)
        {
            //如果还没有进行实例化,那么可以创建唯一的实例,自己调用private中的构造函数
            pInstance = new Singleton();
            return pInstance;
        }
        else
        {
            //如果已经进行了实例化,那么就直接返回已经再全局静态区创建的实例即可
            return pInstance;
        }
    }

    static void destory()
    {
        //防止double delete
        if (pInstance)
        {
            delete pInstance;
            pInstance = NULL;
        }
    }

private:
    //将构造函数与析构函数都进行私有化,这样便不能直接实例化类
    Singleton() {}
    ~Singleton() {}

    static Singleton *pInstance; //这里必须用static修饰的原因是因为getInstance函数也是static修饰的
};

Singleton *Singleton::pInstance = NULL;


int main(){
    Singleton *p1 = Singleton::getInstance();
    p1->print();
    //指针对象的destory应该与NULL连起来,不然之后p1仍能够使用,会发生错误!
    p1->destory();
    p1 = NULL;
    p1->a = 5;
    cout << p1->a << endl;
    return 0;
}

2.饿汉模式

Singleton* Singleton::_pInstance = new Singleton();说明了这个是饿汉模式,需要在类加载的时候就申请对象,这样的话就是线程安全的状态。

#include <iostream>
using std::cout;
using std::endl;

class Singleton{
public:
    static Singleton* getInstance()
    {
        return _pInstance;
    }

    static void destory(){
        if (_pInstance){
            delete _pInstance;
            _pInstance = NULL;
        }
    }

private:
    Singleton(){ cout << "Singleton()" << endl;}
    ~Singleton(){cout << "~Singleton()" << endl;}
    static Singleton* _pInstance;
};

//Singleton* Singleton::_pInstance = NULL;//这是懒汉模式,线程不安全
Singleton* Singleton::_pInstance = new Singleton();//这是饿汉模式,线程安全


int main(){
    Singleton* p1 = Singleton::getInstance();
    Singleton* p2 = Singleton::getInstance();
    cout << p1 << endl;
    cout << p2 << endl;
    p1->destory();
    p2->destory();
    return 0;
}


template+单例模式:可以创建任何类的单例

问题:实现一个模板形式的单例类,要求对于任意类型的类经过Singleton的处理之后,都能获取一个单例对象,并且可以传递任意参数。

 Point pt(1, 2);
 Point pt2(3, 4);
 
 Computer com("Mac", 8888);
 
 
 int main(void)
 {
    Computer * p1 = Singleton<Computer>::getInstance("Xiaomi", 6666);
    Computer * p2 = Singleton<Computer>::getInstance("Xiaomi", 6666);
    
    Point * p3 = Singleton<Point>::getInstance(1, 2);
    Point * p4 = Singleton<Point>::getInstance(1, 2);
    
    return 0;
 } 

思路:Singleton类中真正起着作用的是_pInstance这个指针,只需要将指针类型转换为模板型即可。


Singleton.h:

#ifndef _MY_QUEUE_H_
#define _MY_QUEUE_H_
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;


namespace wd
{

class Point{
public:
    template<typename... Args>
    Point(Args... args){}
    ~Point(){}
};


class Computer{
public:
    template<typename... Args>
    Computer(Args... args){}
    ~Computer(){}
};

template<class T>
class Singleton{
public:
    template<typename... Args>
    static T* getInstance(Args... args){
        if (!_pInstance){
            _pInstance = new T(args...);
        }
        return _pInstance;
    }

    static void destory(){
        if (_pInstance){
            delete _pInstance;
            _pInstance = NULL;
        }
    }


private:
    Singleton(){}
    ~Singleton(){}
    static T* _pInstance; 
};

template<class T>
T* Singleton<T>::_pInstance = NULL;//懒汉模式

} //end of namespace wd

#endif

main.cpp:

#include "Singleton.h"
using namespace wd;

//多参数测试
void test0(){
    Computer c1("ASUS", 6666);
    Computer c2("Mac", 9999);
    Point p1(3,4);
    Point p2 ("sdf", 'a');

}

//单例测试
void test1(){
    Computer *c1 = Singleton<Computer>::getInstance("ASUS", 6666);
    Computer *c2 = Singleton<Computer>::getInstance("ASUS", 6666);
    cout << c1 << endl;
    cout << c2 << endl;
    //Singleton<Computer>::destory();

    Point *p1 = Singleton<Point>::getInstance(1,2);
    Point *p2 = Singleton<Point>::getInstance("dfas",'as');
    cout << p1 << endl;
    cout << p2 << endl;
    Singleton<Point>::destory();    
}

int main()
{
    test1();
    return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值