设计模式(1)-单例模式

来源:互联网 发布:2t硬盘恢复数据多少钱 编辑:程序博客网 时间:2024/05/22 01:26

设计模式是一种经验的总结,有经验的面向对象设计者在不断的开发试错、总结中得到了一些面向不同场景不同需求的设计经验,经过不断的验证,基于这些经验的某种面向对象的设计风格被认为是某种意义上的最佳实践。
当然是不是真的有最佳实践这种东西呢,我个人觉得,在大部分时候,我们可以照搬某个基本的设计模式,应用到我们自己的项目中去,但是实际项目中,也会有很多问题,必须要根据实际的情况对这些模式进行一些变形。
所以原理和思想是重点,熟悉常用的设计模式有助于我们解决设计问题和提高代码质量,最重要的是我们不用去试错。学习设计模式是必要的,因为这让我们站在巨人的肩膀上。
我们常用的设计模式之一是单例模式,也是设计模式中最特别和最易理解的一种设计模式。

单例模式

思路:

单例模式生成且只生成一个全局对象,这种对象通常被其他不同的对象使用在不同的地方,使用一个全局对象的好处是保证状态。事实上单例模式是可以被静态函数和静态成员替代的,只是我们从面向对象的角度来讲,将这些方法和成员封闭起来是更好的设计。所以其实单例也是基于静态成员和变量的。单例实例化后本身就成为一个静态指针指向的对象。
值得一提的是,为了确保只有一个实例,让类自身去维护这样一个静态对象是最好的选择,因为这意味着,我们可以像平常创建一个对象一个直接“创建”这样一个单例对象(实际上可能是获取一个已有的对象),这样在使用上我们不会觉得和普通对象有太多区别,当然普通对象可能需要delete(谁创建,谁释放),单例基本不需要(单例类内部new的空间,由单例类内部delete)。

结构

这里写图片描述

代码

//singleton.hclass Singleton{public:    static Singleton* getInstance();protected:    Singleton();private:    static Singleton* _instance;}//singleton.cppSingleton* Singleton::_instance=0;Singleton* Singleton::getInstance(){    if(!_instance)    {        _instance=new Singleton();//我在这里使用了new分配了空间,那在哪里delete呢?这是一个问题    }    return _instance;}//mainvoid main(){    auto single=Singleton::getInstance();    //这样,一个Singleton实例单例就被**创建并获取**,可以使用了。    auto s=Singleton::getInstance();    //s==single}

将构造函数定义为protected,将实例指针_instance设为private,用户就只能通过一个getInstance方法得到单一实例,不管之前实例状态如何,只要用户需要,返回这一实例即可。
一个基本的单例示例如上所示,对于了解单例的使用是足够的,但是我们发现一个问题,写在上面示例的代码注释中。如果我们在类内部使用了new,那么谁来负责释放这一对象?根据谁创建谁释放的原则,当然是这个单例类自身最好。所以我们在上面的示例中作一些修改:
在Singleton内部定义一个GC类专门用来负释放Singleton的实例对象内存,并且这个定义一个GC对象在Singleton内部,这样程序退出时,这个gc会被释放,从而调用他的析构函数执行释放Singleton实例内存的功能,将他们申明为private是防止被外部对象滥用。

class Singleton{public:    static Singleton* getInstance();protected:    Singleton();private:    static Singleton* _instance;---------------注意和上面单例类定义的区别就在这里------------    //GC类的唯一价值就是释放new出来的单例    class GC    {    public:        ~GC()        {            if (_instance)            {                delete instance;                instance= NULL;            }        }    };    static GC gc;//程序退出时,释放这个静态对象,然后执行内存释放}

应用场景

一个游戏的主角可能只有一个,那么当然可以使用单例模式。或者一个工厂(Factory模式)实例只需要一个,也可以使用单例模式。

注意事项

单例模式有一些变形,比如多例模式,但基础是单例模式。单例模式由于是全局对象,在多线程环境下,应尤其注意,如果有必要的话可以根据多线程编程的加锁方法在单例类中实现加锁防止竞争出错。

原创粉丝点击