C++实现设计模式之--单例模式

C++实现设计模式之–单例模式

在程序中,会经常使用new来创建对象,特别是在后期,程序越来越复杂,那么对对象的管理就特别的复杂,所有对在程序运行过程中只需要一个对象,并对其进行操作的类,继承单例模式,从而方便管理。例如网络游戏运行中,只需要创建一个网络的对象,来实现数据的发送,或者是游戏中全局管理对象。很形象的例子就是,一部电影,总导演只有一个,不可能有很多个导演,导演来控制整部电影改怎么拍。

单例的实现方式有很多种,最简单的一种实现方式如下:

方式一

class Singleton
{
public:

    static Singleton* getInstance() {
        if (nullptr== _instance ) {
            _instance = new Singleton();
        }
        return _instance;
    }


private:
    static Singleton* _instance;

};

当然在实际开发中,不可能为每一个类写一个单例方法,所以可以设计成模板,让需要实现单例的类继承该模板,模板实现如下:

template<typename T>
class ApplicationSingleTon
{
public:
    static T* getInstance() {
        if (_instance == nullptr) {
            _instance = new T();
        }
        return _instance;
    }
private:
    static T* _instance;
}
template <typename T>
T* ApplicationSingleTon<T>::_instance = nullptr;

在需要实现单例的类继承该模板, 如

#define  Director_Ins Director::getInstance();
class Director : public ApplicationSingleTon<Director>
{
public:
    void display() {
        std::cout<<"singleton director!";   
    };
};

为了方便,直接定义了宏,在需要调用该对象的地方,直接调用Director_Ins 便可以。这种单例的实现,相对简单,缺点是在多线程的情况下,可能会创建多个Singleton实例。比如这么一种情况,线程A和线程B同事达到if NUll这里,A,B都判断为NULL,所以都执行了new操作,这是就创建了两个对象。所以这个时候就出现个了另外一种实现方式。

方式二

std::mutex m;
class Singleton
{
public:
    static Singleton* getInstance() {
        if (_instance == NULL) {
            if (_instance == NULL) {
                m.lock();
                _instance = new Singleton();
            }
            m.unlock();
        }
        return _instance;
    }
private:
    static Singleton* _instance;
};
Singleton* Singleton::_instance = NULL;

通过增加一个互斥锁,来避免多线程访问时重新创建对象的问题。细心的你可能会发现,这个版本的getinstance中,对_instance进行两次是否为NULL的判断,为什么要这样做呢。利用双检锁,利用两次判断,减少了加锁/解锁的操作,主要保证了线程的安全。这种方式就很有效的解决了上面那种方式所带了的问题,在这种方式下,再遇到上面那种情况,当同时到达判断为null,然后会加锁,此时在判断一次是否为null,用来确定该对象还未创建,确保了全程只有一个对象被创建。这种方式的缺点是当对大数据进行操作的时候,就会出现性能瓶颈,于是又有第三种方式:

方式三

class Singleton
{
public:

    static Singleton* getInstance() {
        return const_cast<Singleton*>(_instance);
    }


private:
    static const Singleton* _instance;  
};
const Singleton* Singleton::_instance = new Singleton();

这种方式将对象的初始化放在了静态初始化阶段,这样,在运行mian函数之前就已经将该对象初始化,不再需要在运行过程中创建。但是这样一来就出现了另外一个问题,对象的销毁,因为静态成员的生命周期是程序运行期间,知道程序运行结束,所以这种方式只适用于在整个程序运行期间一直存在的对象。

介绍了这么多单例模式实现的方式,都主要是对象的创建,但是对象有创建,就必定会有销毁,这时你可能会问了,都设计成单例类了,肯定是整个程序运行的过程中会一直需要的啊。说的对,但是有这样的特殊情况,如连接数据库的类,肯定要在程序结束前释放对象
参考了果冻想的博客,借鉴他的实现方式:

class Singleton
{
public:
    static Singleton* getInstance() {
        return _instance;
    }
private:
    static Singleton* _instance;
    class Release
    {
    public:
        ~Release()
        {
            if (_instance != NULL)
            {
                delete _instance;
                _instance = NULL;
            }
        }
    };
    static Release rl;
};
Singleton* Singleton::_instance = new Singleton();
Singleton::Release Singleton::rl;

在此感谢果冻想博客给与的思路与见解。


果冻想C++设计模式——单例模式: http://www.jellythink.com/archives/82

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值