单例模式
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。即一个类只有一个对象实例
要点
显然单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
从具体实现角度来说,就是以下三点:一是单例模式的类只提供私有的构造函数,二是类定义中含有一个该类的静态私有对象,三是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。
优缺点
优点
一、实例控制
单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
二、灵活性
因为类控制了实例化过程,所以类可以灵活更改实例化过程。
缺点
一、开销
虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
二、可能的开发混淆
使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
三、对象生存期
不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。
单例模式顾名思义,就是在系统中只允许产生这个类的一个实例。
实例说明:很多大臣拜见的皇帝,只有一个。体现在面向对象方面,CEmperor定义一个静态指针,和一个静态函数,私有化构造函数、析构函数、构造函数复制、重载赋值语句。
注意:线程安全,采用互斥体的方式实现
用单例的方式实现Emperor,不论在使用过程中new多少次均只会有一个实例
实例说明:很多大臣拜见的皇帝,只有一个。体现在面向对象方面,CEmperor定义一个静态指针,和一个静态函数,私有化构造函数、析构函数、构造函数复制、重载赋值语句。
注意:线程安全,采用互斥体的方式实现
用单例的方式实现Emperor,不论在使用过程中new多少次均只会有一个实例
//Emperor.h #pragma once #include <Windows.h> #include <winnt.h> #include <iostream> using std::cout; using std::endl; using std::string; class Emperor { public: static Emperor* getInstance(); static void releaseInstance(); void emperorInfo(void); void setEmperorTag(string tag); private: Emperor(void); virtual ~Emperor(void); Emperor(const Emperor&); Emperor& operator=(const Emperor&); static Emperor *m_emperor; static HANDLE m_mutex; string m_emperor_tag; class Garbo { public: Garbo() { cout << "create garbo" << endl; } ~Garbo() { cout << "destrory garbo" << endl; getchar(); if(NULL != m_emperor) { WaitForSingleObject(m_mutex, INFINITE); if(NULL != m_emperor) { cout << "remove instance" << endl; delete m_emperor; m_emperor = NULL; } ReleaseMutex(m_mutex); } if(NULL != m_mutex) { cout << "delete mutex" << endl; CloseHandle(m_mutex); m_mutex = NULL; } } }; static Garbo m_garbo; };
//Emperor.cpp #include "stdafx.h" #include "Emperor.h" #include <iostream> using std::cout; using std::endl; using std::string; Emperor *Emperor::m_emperor = NULL; HANDLE Emperor::m_mutex = CreateMutex(NULL, FALSE, NULL); Emperor::Garbo Emperor::m_garbo; Emperor::Emperor(void) { cout << "create emperor instance" << endl; } Emperor::~Emperor(void) { cout << "destroy emperor instance and release its resources" << endl; } void Emperor::emperorInfo(void) { char msg_buf[50] = {0}; sprintf_s(msg_buf, 50, "the emperor's name is (%s)", m_emperor_tag.c_str()); string msg(msg_buf); cout << msg.c_str() << endl; } Emperor *Emperor::getInstance() { if(NULL == m_emperor) { WaitForSingleObject(m_mutex, INFINITE); if(NULL == m_emperor) m_emperor = new Emperor(); ReleaseMutex(m_mutex); } return m_emperor; } void Emperor::releaseInstance() { if(NULL != m_emperor) { WaitForSingleObject(m_mutex, INFINITE); if(NULL != m_emperor) { delete m_emperor; m_emperor = NULL; } ReleaseMutex(m_mutex); } } void Emperor::setEmperorTag(string tag) { m_emperor_tag = tag; }
实例测试
// SingletoPatternDemo.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include "Emperor.h" int _tmain(int argc, _TCHAR* argv[]) { Emperor *pEmperor1 = Emperor::getInstance(); pEmperor1->setEmperorTag("QL"); pEmperor1->emperorInfo(); Emperor *pEmperor2 = Emperor::getInstance(); pEmperor2->emperorInfo(); Emperor *pEmperor3 = Emperor::getInstance(); pEmperor3->emperorInfo(); Emperor::releaseInstance(); getchar(); return 0; }
单例模式比较简单,但在项目中使用的时候,需要明确只调用CEmperor的GetInstance函数来获取实例
转载自http://blog.csdn.net/phiall/article/details/52199659