模式动机
对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。
如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。
一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的模式动机。

模式定义
单例模式(Singleton Pattern):单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。
单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。单例模式是一种对象创建型模式。单例模式又名单件模式或单态模式。
Singleton Pattern: Ensure a class has only one instance and provide a global point of access to it.
Frequency of use: medium high
UML图

模式结构
单例模式包含如下角色:
Singleton:单例

模式分析
单例模式的目的是保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例模式包含的角色只有一个,就是单例类——Singleton。单例类拥有一个私有构造函数,确保用户无法通过new关键字直接实例化它。除此之外,该模式中包含一个静态私有成员变量与静态公有的工厂方法,该工厂方法负责检验实例的存在性并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。

在单例模式的实现过程中,需要注意如下三点:
单例类的构造函数为私有;
提供一个自身的静态私有成员变量;
提供一个公有的静态工厂方法。

实例:身份证号码
在现实生活中,居民身份证号码具有唯一性,同一个人不允许有多个身份证号码,第一次申请身份证时将给居民分配一个身份证号码,如果之后因为遗失等原因补办时,还是使用原来的身份证号码,不会产生新的号码。
Singleton.cs

namespace SingletonPattern
{
class Singleton
{
private static Singleton instance;
//构造方法让其private,这就堵死了外界利用new创建此类实例的可能
private Singleton()
{
}
//此方法是获得本类实例的唯一全局访问点
public static Singleton GetInstance()
{
//若实例不存在,则new一个新实例,否则返回已有的实例
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}

客户端代码

using System;

namespace SingletonPattern
{
class Program
{
static void Main(string[] args)
{
Singleton s1 = Singleton.GetInstance();
Singleton s2 = Singleton.GetInstance();
if (s1 == s2)
{
Console.WriteLine("两个对象是相同的实例");
} Console.Read();
}
}
}

单例模式的优点
 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它,并为设计及开发团队提供了共享的概念。
 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。
 允许可变数目的实例。我们可以基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例。

单例模式的缺点
 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
 单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。
 滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出;现在很多面向对象语言(如Java、C#)的运行环境都提供了自动垃圾回收的技术,因此,如果实例化的对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致对象状态的丢失。

模式适用环境
在以下情况下可以使用单例模式:
 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器,或者需要考虑资源消耗太大而只允许创建一个对象。
 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。
 在一个系统中要求一个类只有一个实例时才应当使用单例模式。反过来,如果一个类可以有几个实例共存,就需要对单例模式进行改进,使之成为多例模式。

深入浅出设计模式——单例模式(Singleton Pattern)的更多相关文章

  1. 浅谈设计模式--单例模式(Singleton Pattern)

    题外话:好久没写blog,做知识归纳整理了.本来设计模式就是个坑,各种文章也写烂了.不过,不是自己写的东西,缺少点知识的存在感.目前还没做到光看即能记住,得写.所以准备跳入设计模式这个大坑. 开篇先贡 ...

  2. 设计模式之单例模式(Singleton Pattern)

    单例模式 单例模式(Singleton Pattern)在java中算是最常用的设计模式之一,主要用于控制控制类实例的数量,防止外部实例化或者修改.单例模式在某些场景下可以提高系统运行效率.实现中的主 ...

  3. 乐在其中设计模式(C#) - 单例模式(Singleton Pattern)

    原文:乐在其中设计模式(C#) - 单例模式(Singleton Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 单例模式(Singleton Pattern) 作者:weba ...

  4. 设计模式系列之单例模式(Singleton Pattern)——确保对象的唯一性

    模式概述 模式定义 模式结构图 饿汉式单例与懒汉式单例 饿汉式单例 懒汉式单例 模式应用 模式在JDK中的应用 模式在开源项目中的应用 模式总结 主要优点 适用场景 说明:设计模式系列文章是读刘伟所著 ...

  5. 【设计模式】单例模式 Singleton Pattern

    通常我们在写程序的时候会碰到一个类只允许在整个系统中只存在一个实例(Instance)  的情况, 比如说我们想做一计数器,统计某些接口调用的次数,通常我们的数据库连接也是只期望有一个实例.Windo ...

  6. 二十四种设计模式:单例模式(Singleton Pattern)

    单例模式(Singleton Pattern) 介绍保证一个类仅有一个实例,并提供一个访问它的全局访问点. 示例保证一个类仅有一个实例. Singleton using System; using S ...

  7. 抽象工厂(Abstract Factory),工厂方法(Factory Method),单例模式(Singleton Pattern)

    在谈工厂之前,先阐述一个观点:那就是在实际程序设计中,为了设计灵活的多态代码,代码中尽量不使用new去实例化一个对象,那么不使用new去实例化对象,剩下可用的方法就可以选择使用工厂方法,原型复制等去实 ...

  8. 十次艳遇单例设计模式(Singleton Pattern)

    1.引言 单例设计模式(Singleton Pattern)是最简单且常见的设计模式之一,在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访 ...

  9. 设计模式 单例模式(Singleton) [ 转载2 ]

    设计模式 单例模式(Singleton) [ 转载2 ] @author java_my_life 单例模式的结构 单例模式的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一实例. 单例类 ...

随机推荐

  1. UrlRewriteFilter

    UrlRewriteFilter是一个改写URL的Java Web过滤器,可见将动态URL静态化.适用于任何Java Web服务器(Resin,Jetty,JBoss,Tomcat,Orion等).与 ...

  2. Android 6.0 权限管理

    google官方例子: https://github.com/googlesamples/android-RuntimePermissions Android 6.0在我们原有的AndroidMani ...

  3. syslog日志系统

    目前,linux依旧使用syslogd作为日志监控进程,而在主流的linux发行版中依旧使用sysklog这个比较老的日志服务器套件.从前一篇日志可以看到,对其进行必要的配置能减少很多麻烦,并且可更有 ...

  4. Linux下查看系统版本号信息的方法(转)

    一.查看Linux内核版本命令: 1.cat /proc/version [root@localhost ~]# cat /proc/versionLinux version 2.6.18-194.8 ...

  5. Sql用变量拼语句

    CREATE PROC Test_GetCollegeInfo @type int AS BEGIN ),@v int,@sql nvarchar(max) Begin )) END ELSE BEG ...

  6. C# 遍历类的属性并取出值

    最近悟出来一个道理,在这儿分享给大家:学历代表你的过去,能力代表你的现在,学习代表你的将来. 十年河东十年河西,莫欺少年穷 学无止境,精益求精    今天有点胡思乱想,想遍历MVC Model的属性并 ...

  7. c#读取Word模板,利用书签替换内容包括表格

    //生成WORD程序对象和WORD文档对象 Microsoft.Office.Interop.Word.Application appWord = new Microsoft.Office.Inter ...

  8. 模板 BFS

    [模板]BFS #include <stdio.h> #include <string.h> #include <queue> using namespace st ...

  9. 关于system函数的安全性漏洞

    当以一个普通用户去执行  设置-用户ID 为root的程序时,如果再次用了system函数时,被system函数所执行的那个程序具有 有效-用户ID 为root的风险(虽然真实用户还是普通用户),这也 ...

  10. c#与.net的简介

    c语言诞生于上世纪60年代,后来诞生了面向对象的c++,后来出现看更为精简的java,微软之后又出了c#语言.早期的c#语言和java语言类似.经过长足的发展,c#变得越来越完美. 面向对象 简单,安 ...