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

来源:互联网 发布:手板编程招聘 编辑:程序博客网 时间:2024/06/04 19:48

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

0 0