也谈单件模式类的设计(C++)

来源:互联网 发布:北大青鸟学编程 编辑:程序博客网 时间:2024/05/17 05:56

单件模式在设计模式中是比较基本的模式之一,它是用来构造在整个应用中只有唯一实例的对象。今天在CODE的过程中采用单件模式实现了一个类,大至如下:

 class Device: public BaseDevice
{
private:
    int m_port;
    ...
private:
    Device();
    Device& operator=(const Device&);

    static Device* _instance;
    ...

public:
    DWORD Initialize();
    ~Device();

public:
    static Device* Instance();

};

Device *Device::_instance = NULL;

Device::Device()
{   ...   }

Device::~Device()
{    }

DWORD Device::Initialize()
{  ...  }

Device* Device::Instance()
{
    if(NULL==_instance)
    {
        _instance=new Device();
    }
    return _instance;
}

这样一个简单的单件实例类就实现好了,那么它的实例在应用过程中就是唯一的了吗?当然是的。单件模式要实现目标就是这样。但我在编程过程中遇到了一个问题——上面的代码存在着BUG:当对单件对象delete后然后再获取实例并调用其的方法时出现访问地址错误?
Device*dv=Device::Instance();
if(dv)
  dv->Initialize();
...
delete dv;
dv=NULL;
...
dv=Device::Instance();
if(dv)
  dv->Initialize();      //在这里调用出错

如果只看这段代码很难察觉到错误,因为这些都是正常的。DEBUG了半天才找到了错误的根源——错误还是出在单件类的设计和实现上。为了使对象的实例唯一,我们使类的构造函数私有,公开类静态成员函数获得实例,对象的实例保存在类的静态成员变量中。客户端每次调用Instance返回的是这个静态成员变量。那为什么在delete之后重新获得实例却出现访问地址错误呢,明明看到第二个dv指针不是NULL值啊?问题就出在析构函数那:没有对静态变量_instance=NULL。因为在执行delete操作时,其实对象的实例已经得到释放了,只是这时的_instance指针没有赋NULL值,依然指向最初创建对象的那个地址!这就是所谓的“野指针”吧。

Device::~Device()
{
    Device::_instance=NULL;
}

更进一步的想,在单件模式的设计应该也分几种情况。像上面那种方式,实例是唯一,但可以被应用端随时释放并再创建,另一种我想是把析构函数也私有化,这样应用端就不能释放,但是怎么创建呢?这就需要配合其它的设计模式吧,比如抽象工厂,专门负责对象的创建和释放。

原创粉丝点击