设计模式(c++)笔记之三(Singleton单例模式)

本文深入探讨了Singleton模式的基本概念及其在面向对象设计中的重要性。通过引用实际例子,如皇帝作为单例模式的典型应用场景,解释了如何通过维护静态成员变量来确保对象的唯一性。同时,提供了具体的实现代码,包括类图和关键函数的详细说明,以展示如何在实际项目中实现和利用Singleton模式。此外,文章还强调了线程安全的实现策略,确保了模式在多线程环境下的正确性。
摘要由CSDN通过智能技术生成

一、简介

   

    单例模式看起来也蛮简单的,就是在系统中只允许产生这个类的一个实例。

    个人认为 Singleton 模式是设计模式中最为简单、最为常见、最容易实现,也是最应该熟悉和掌握的模式。且不说公司企业在招聘的时候为了考察员工对设计的了解和把握,考的最多的就是 Singleton 模式。

    Singleton 模式解决问题十分常见,我们怎样去创建一个唯一的变量(对象)?在基于对象的设计中我们可以通过创建一个全局变量(对象)来实现,在面向对象和面向过程结合的设计范式(如 C++中)中,我们也还是可以通过一个全局变量实现这一点。但是当我们遇到了纯粹的面向对象范式中,这一点可能就只能是通过 Singleton 模式来实现了,可能这也正是很多公司在招聘 Java 开发人员时候经常考察 Singleton 模式的缘故吧。 

    Singleton 模式典型的结构图为: 


图 2-1:Singleton Pattern 结构图


    在 Singleton 模式的结构图中可以看到,我们通过维护一个 static 的成员变量来记录这个唯一的对象实例。通过提供一个staitc 的接口instance 来获得这个唯一的实例。 


二、实例:


    这个模式是很有意思,而且比较简单,但是我还是要说因为它使用的是如此的广泛,如此的有人缘,单例就是单一、独苗的意思,那什么是独一份呢?你的思维是独一份,除此之外还有什么不能山寨的呢?我们举个比较难复制的对象:皇帝。

    中国的历史上很少出现两个皇帝并存的时期,是有,但不多,那我们就认为皇帝是个单例模式,在这个场景中,有皇帝,有大臣,大臣是天天要上朝参见皇帝的,今天参拜的皇帝应该和昨天、前天的一样(过渡期的不考虑,别找茬哦),大臣磕完头,抬头一看,嗨,还是昨天那个皇帝,单例模式,绝对的单例模式,先看类图: 


注释:

    main(),大臣

    CEmperor,需要单例的类

    说明:很多大臣拜见的皇帝,只有一个。体现在面向对象方面,CEmperor定义一个静态指针,和一个静态函数,私有化构造函数、析构函数、构造函数复制、重载赋值语句。

    注意:线程安全,采用互斥体的方式实现。


本人工程目录:


      


三、实现代码:


实现单例类Emperor

Emperor.h

#pragma once
#include <Windows.h>
#include <process.h>
#include <iostream>
using std::cout;
using std::endl;
using std::string;


class CEmperor
{
public:
	static CEmperor *GetInstance();
	static void ReleaseInstance();
	void EmperorInfo(void);
	void SetEmperorTag(string tag);
private:
	CEmperor(void);
	virtual ~CEmperor(void);
	CEmperor(const CEmperor&);
	CEmperor& operator = (const CEmperor&);
	static CEmperor *m_pEmperor;
	static HANDLE m_pMutex;
	string m_EmperorTag;
	class CGarbo
	{
	public:
		CGarbo(){cout<< "Create Garbo" <<endl;}
		~CGarbo()
		{
			cout<<"Destroy Garbo"<<endl;
			if (NULL != m_pEmperor)
			{
				WaitForSingleObject(m_pMutex,INFINITE);
				if (NULL != m_pEmperor)
				{
					cout << "Remove instance" <<endl;
					delete m_pEmperor;
					m_pEmperor = NULL;
				}
				ReleaseMutex(m_pMutex);
			}
			if (NULL != m_pMutex)
			{
				cout<<"Delete mutex" <<endl;
				CloseHandle(m_pMutex);
				m_pMutex = NULL;
			}

		}
	};
	static CGarbo m_Garbo;
};
Emperor.cpp

#include "Emperor.h"
CEmperor* CEmperor::m_pEmperor = NULL;
HANDLE CEmperor::m_pMutex = CreateMutex(NULL,false,NULL);
CEmperor::CGarbo CEmperor::m_Garbo;


CEmperor::CEmperor(void)
{
	cout<<"Create CEmperor Instance" <<endl;
}


CEmperor::~CEmperor(void)
{
	cout << "Destroy CEmperor Instance and release its resource"<<endl;
}

void CEmperor::EmperorInfo(void)
{
	char msgBuffer[50] = {0};
	sprintf_s(msgBuffer,50,"皇帝某年某日......(%s).",m_EmperorTag.c_str());
	string msg(msgBuffer);
	cout << msg.c_str()<<endl;
}

CEmperor* CEmperor::GetInstance()
{
	if (NULL == m_pEmperor)
	{
		WaitForSingleObject(m_pMutex,INFINITE);
		if (NULL == m_pEmperor)
			m_pEmperor = new CEmperor();
		ReleaseMutex(m_pMutex);
	}
	return m_pEmperor;
}

void CEmperor::ReleaseInstance()
{
	
	if (NULL != m_pEmperor)
	{
		WaitForSingleObject(m_pMutex,INFINITE);
		if (NULL != m_pEmperor)
		{
			delete m_pEmperor;
			m_pEmperor = NULL;
		}
		ReleaseMutex(m_pMutex);
	}
	
}

大臣类main

main.cpp

#include <iostream>
#include "Emperor.h"
using std::cout;
using std::endl;

void DoIt()
{
	CEmperor *pEmperor1 = CEmperor::GetInstance();
	//pEmperor1->SetEmperorTag("95");
	pEmperor1->EmperorInfo();

	CEmperor *pEmperor2 = CEmperor::GetInstance();
	pEmperor2->EmperorInfo();

	CEmperor *pEmperor3 = CEmperor::GetInstance();
	pEmperor3->EmperorInfo();

	CEmperor *pEmperor4 = pEmperor3;
	pEmperor4->EmperorInfo();

	CEmperor *pEmperor5 = NULL;
	pEmperor5 = pEmperor4;
	pEmperor5->EmperorInfo();

	CEmperor::ReleaseInstance();
}

int main(int argc ,const char* argv[])
{
	DoIt();
	//cout<<"helloworld";
}

调度结果:




参考文献:《设计模式之禅》,《GoF_23种设计模式解析》

参考博客:http://www.cnblogs.com/wanggary/archive/2011/04/09/2010876.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热血枫叶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值