单例模式

  单例模式也称为单件模式、单子模式,可能是使用最广泛的设计模式。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。如系统的日志输出,GUI应用必须是单鼠标,MODEM的联接需要一条且只需要一条电话线,操作系统只能有一个窗口管理器,一台PC连一个键盘。单例模式有两种:饿汉式单例类和懒汉式单例类。

适用性:

  单例模式常常与工厂模式结合使用,因为工厂只需要创建产品实例就可以了,在多线程的环境下也不会造成任何的冲突,因此只需要一个工厂实例就可以了。

优点:

  1.减少了时间和空间的开销(new实例的开销)。

  2.提高了封装性,使得外部不易改动实例。

缺点:

  1.懒汉式是以时间换空间的方式。

  2.饿汉式是以空间换时间的方式。

饿汉式单例类

//外部初始化 before invoke main
const Singleton* Singleton::m_instance = new Singleton; class Singleton
{
private:
static const Singleton* m_instance;
Singleton(){}
public:
static const Singleton* getInstance()
{
return m_instance;
}
};

懒汉式单例类

class Singleton
{
private:
static Singleton* m_instance;
Singleton() {}
public:
static Singleton* getInstance();
}; Singleton* Singleton::getInstance()
{
if(NULL == m_instance)
{
m_instance = new Singleton;
} return m_instance;
}

但是在多线程的环境下却不行了,因为很可能两个线程同时运行到if (m_instance == NULL)这一句,导致可能会产生两个实例。于是就要在代码中加锁。

Singleton* getInstance()
{
lock();
if (instance == NULL)
{
instance= new Singleton();
}
unlock(); return instance;
}

但这样写的话,会稍稍影响性能,因为每次判断是否为空都需要被锁定,如果有很多线程的话,就爱会造成大量线程的阻塞。于是大神们又想出了双重锁定。

Singleton* getInstance()
{
if (instance == NULL)
{
lock();
if (instance == NULL)
{
instance = new Singleton();
}
unlock();
} return instance;
}

这样只够极低的几率下,通过越过了if (instance == NULL)的线程才会有进入锁定临界区的可能性,这种几率还是比较低的,不会阻塞太多的线程,但为了防止一个线程进入临界区创建实例,另外的线程也进去临 界区创建实例,又加上了一道防御if (instance == NULL),这样就确保不会重复创建了。

使用

#include <iostream>
using namespace std; // 单例模式
class Singleton
{
private:
Singleton() {}; // 不允许直接构造其对象
static Singleton *instance; public:
static Singleton* createInstance()
{
if(!instance)
{
// 对象第一次被创建,允许
cout << "创建新对象" << endl;
instance = new Singleton();
}
else
{
// 请求再次创建对象,不允许
cout << "已经创建过对象了,返回原对象" << endl;
} return instance;
} void getAddress()
{
cout << "我的地址是 " << instance << endl;
}
}; Singleton* Singleton::instance = ; //在初始化的时候,不能在前面加static了 int main()
{
//Singleton s;//报错:无法访问 private 成员(在“Singleton”类中声明)
Singleton *s1 = Singleton::createInstance();
s1->getAddress();
cout << endl << endl; Singleton *s2 = Singleton::createInstance();
s2->getAddress();
return ;
}

设计模式 --> (2)单例模式的更多相关文章

  1. 设计模式之单例模式(Singleton)

    设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...

  2. GJM : C#设计模式(1)——单例模式

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...

  3. java设计模式之单例模式(几种写法及比较)

    概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...

  4. 每天一个设计模式-4 单例模式(Singleton)

    每天一个设计模式-4 单例模式(Singleton) 1.实际生活的例子 有一天,你的自行车的某个螺丝钉松了,修车铺离你家比较远,而附近的五金店有卖扳手:因此,你决定去五金店买一个扳手,自己把螺丝钉固 ...

  5. 设计模式之单例模式的简单demo

    /* * 设计模式之单例模式的简单demo */ class Single { /* * 创建一个本类对象. * 和get/set方法思想一样,类不能直接调用对象 * 所以用private限制权限 * ...

  6. 设计模式之单例模式——Singleton

                        设计模式之单例模式--Singleton 设计意图: 保证类仅有一个实例,并且可以供应用程序全局使用.为了保证这一点,就需要这个类自己创建自己的对象,并且对外有 ...

  7. 10月27日PHP加载类、设计模式(单例模式和工厂模式)、面向对象的六大原则

    加载类可以使用include.require.require_once三种中的任意一种,每个关键字都有两种方法,但是这种方法的缺点是需要加载多少个php文件,就要写多少个加载类的方法.一般也就需要加载 ...

  8. java 23 - 2 设计模式之单例模式

    单例模式:保证类在内存中只有一个对象. 如何保证类在内存中只有一个对象呢?  A:把构造方法私有  B:在成员位置自己创建一个对象  C:通过一个公共的方法提供访问 单例模式之饿汉式: (一进来就造对 ...

  9. [转]JAVA设计模式之单例模式

    原文地址:http://blog.csdn.net/jason0539/article/details/23297037 概念: java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主 ...

  10. python_way,day8 面向对象【多态、成员--字段 方法 属性、成员修饰符、特殊成员、异常处理、设计模式之单例模式、模块:isinstance、issubclass】

    python_way day8 一.面向对象三大特性: 多态 二.面向对象中的成员 字段.方法属性 三.成员修饰符 四.特殊成员 __init__.__doc__.__call__.__setitem ...

随机推荐

  1. android自定义Notification通知栏实例

    项目有个需求,需要在发送Notification的时候动态给定url的图片.大概思路如下:自己定义一个Notification的布局文件,这样能够很方便设置View的属性. 首先加载网络图片,使用Bi ...

  2. linux驱动---字符设备的注册register_chrdev说起

    首先我们在注册函数里面调用了register_chrdev(MEM_MAJOR,"mem",&memory_fops),向内核注册了一个字符设备. 第一个参数是主设备号,0 ...

  3. 【linux】启动apache遇到错误:httpd: Could not reliably determine the server's fully qualified domain name

    1)进入apache的安装目录:(视个人安装情况而不同) [root@server ~]# cd /usr/local/apache/conf 2)编辑httpd.conf文件,搜索"#Se ...

  4. Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in

    1.错误描述 严重: Exception sending context initialized event to listener instance of class org.springframe ...

  5. 如何在BIOS中设置RAID?

    随着价格的下降和相应主板的支持,目前SATA硬盘已经逐渐成为主流.但由于受芯片组和操作系统的影响,不少用户对SATA硬盘的使用及安装系统掌握不足,今天小编就给大家介绍一下SATA硬盘的日常应用技巧,希 ...

  6. firewall服务配置

    /* Border styles */ #table-2 thead, #table-2 tr { border-top-width: 1px; border-top-style: solid; bo ...

  7. 决策树系列(五)——CART

    CART,又名分类回归树,是在ID3的基础上进行优化的决策树,学习CART记住以下几个关键点: (1)CART既能是分类树,又能是分类树: (2)当CART是分类树时,采用GINI值作为节点分裂的依据 ...

  8. Go基础之--操作Mysql(三)

    事务是数据库的一个非常重要的特性,尤其对于银行,支付系统,等等.database/sql提供了事务处理的功能.通过Tx对象实现.db.Begin会创建tx对象,后者的Exec和Query执行事务的数据 ...

  9. 利用SSH端口转发实现跨机器直接访问

    在实际项目测试中经常会遇到数据库操作,但是因为公司安全问题,访问数据库往往需要通过跳板机.但通过跳板机,测试效率大打折扣,因此通过使用SSH端口转发,从而达到跨机器直接访问数据库.实际项目中的应用会比 ...

  10. PHP 数组模糊查询

    function search() { $a=array( '0' => array('id'=>1,'pid'=>0,'name'=>'水果'), '1' => arr ...