【题目】

设计一个类,我们只能生成该类的一个实例。

【分析】

单例模式的意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点。让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可、以被创建(通过截取创建新对象的请求),并且它可以提供一个访问该实例的方法。这就是Singleton模式。

应用场景包括常见的任务管理器、回收站、程序的日志应用、数据库的连接池、操作系统的文件系统、多线程的线程池等等。总体来说单件模式主要用在资源共享的情况下,避免由于各种资源操作导致的性能损耗和资源控制的情况下互相通信,比如线程池。

由于设计模式在面向对象程序设计中起着举足轻重的作用,在面试过程中很多公司都喜欢问一些与设计模式相关的问题。在常用的模式中,Singleton是唯一一个能够用短短几十行代码完整实现的模式。因此,写一个Singleton的类型是一个很常见的面试题。

【解法1】

(1)不好的解法一:只适用于单线程环境

由于要求只能生成一个实例,因此要把构造函数设为私有函数以禁止他人创建实例。我们可以定义一个静态的实例,在需要的时候创建该实例。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 
public sealed class Singleton1
{
    private Singleton1()
    {
    }

private static Singleton1 instance = null;
    public static Singleton1 Instance
    {
        get
        {
            if (instance == null)
                instance = new Singleton1();

return instance;
        }
    }
}

【解法2】

(2)不好的解法二:能适应多线程,但效率低

上述Singleton在单线程下能正常工作,但在多线程的情况下就有问题。为了保证在多线程环境下使用,我们需要加上一个同步锁。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
public sealed class Singleton2
{
    private Singleton2()
    {
    }

private static readonly object syncObj = new object();

private static Singleton2 instance = null;
    public static Singleton2 Instance
    {
        get
        {
            lock (syncObj)
            {
                if (instance == null)
                    instance = new Singleton2();
            }

return instance;
        }
    }
}

上述代码保证了在多线程环境下也只能得到一个实例。但是,Singleton2还不是很完美,每次通过属性Instance得到的Singleton2的实例,都会试图加上一个同步锁,这是一个耗时的操作。

【解法3】

(3)可行的解法:加上同步锁前面两次判断实例是否存在(Dobule-Check)

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
public sealed class Singleton3
{
    private Singleton3()
    {
    }

private static object syncObj = new object();

private static Singleton3 instance = null;
    public static Singleton3 Instance
    {
        get
        {
            if (instance == null)
            {
                lock (syncObj)
                {
                    if (instance == null)
                        instance = new Singleton3();
                }
            }

return instance;
        }
    }
}

【解法4】

(4)强烈推荐的解法一:利用静态构造函数

C#的语法中有一个函数能够确保只用一次,那就是静态构造函数,我们可以利用这个特性实现Singleton模式。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
public sealed class Singleton4
{
    private Singleton4 ()
    {
    }

private static Singleton4 instance = new Singleton4 ();
    public static Singleton4 Instance
    {
        get
        {
            return instance;
        }
    }
}

C#是在调用静态构造函数时初始化静态变量,这样我们就保证只初始化一次instance。但C#中调用静态构造函数是不确定的,而是当.Net运行时发现第一次使用一个类型的时候自动调用该类型的静态构造函数,即第一次用到Singleton4的时候,就会过早地创建实例,降低内存使用效率。

【解法5】

(5)强烈推荐的解法二:实现按需创建实例

Singleton5很好地解决了Singleton4中的实例创建过早的问题。

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
public sealed class Singleton5
{

private Singleton5()
    {
    }

public static Singleton5 Instance
    {
        get
        {
            return Nested.instance;
        }
    }

// nested class
    private class Nested
    {
        static Nested()
        {
        }

internal static readonly Singleton5 instance = new Singleton5();
    }
}

在内存定义一个私有类型,嵌套类,当第一次用到这个嵌套类型的时候,就会调用静态构造函数创建singleton5的实例instance。类型nested只在属性singleton5.instance中用到,由于其私有属性他人无法使用nested类型。因此当我们第一次试图通过属性singleton5.instance得到singleton5的实例时,会自动调用nested的静态构造函数创建实例instance。如果我们不调用属性singleton5.instance,那么就不会触发.NET运行时调用nested,也不会创建实例,这样就真正做到了按需创建。

【参考】

http://zhedahht.blog.163.com/blog/static/2541117420105146828433/

http://www.cppblog.com/dyj057/archive/2005/09/20/346.html

http://www.cnblogs.com/cxjchen/p/3148582.html

http://www.cnblogs.com/panweishadow/archive/2014/04/13.html

http://en.wikipedia.org/wiki/Double-checked_locking

45. Singleton类的C++/C#实现[Singleton]的更多相关文章

  1. C++面试中的singleton类

    引子 “请写一个Singleton.”面试官微笑着和我说. “这可真简单.”我心里想着,并在白板上写下了下面的Singleton实现: 1 class Singleton 2 { 3 public: ...

  2. singleton 类模板限制类只能定义一个对象

    singleton 类模板限制类只能定义一个对象 singleton 类模板限制类只能定义一个对象 singleton 类模板限制类只能定义一个对象 ???

  3. [Android面试题-7] 写出一个Java的Singleton类(即单例类)

    1.首先明确单例的概念和特点: a>单例类只能有一个实例 b>单例类必须自己创建一个自己的唯一实例 c>单例类必须为其他所有对象提供这个实例 2.单例具有几种模式,最简单的两种分别是 ...

  4. C# 用Singleton类构建多线程单例模式

    public sealed class Singleton    {        private static volatile Singleton uniqueInstance;        p ...

  5. SINGLETON(单例模式)---(孤独的人)

    很多时候,我们都很彷徨,因为,在身边的朋友,很少. package patterns.createable.singleton; /** * 孤独的人啊 * 我为你写了一个类 * 这个类,在我们的程序 ...

  6. [Java]类的生命周期(下)类的初始化[转]

    上接深入java虚拟机——深入java虚拟机(二)——类加载器详解(上),在上一篇文章中,我们讲解了类的生命周期的加载和连接,这一篇我们接着上面往下看. 类的初始化:在类的生命周期执行完加载和连接之后 ...

  7. Java虚拟机类加载初始化解析

    Classloader的作用,概括来说就是将编译后的class装载.加载到机器内存中,为了以后的程序的执行提供前提条件. 一段程序引发的思考: 风中叶老师在他的视频中给了我们一段程序,号称是世界上所有 ...

  8. 【原】Java学习笔记020 - 面向对象

    package cn.temptation; public class Sample01 { public static void main(String[] args) { // 成员方法的参数列表 ...

  9. JVM启动过程

    JVM启动过程包括:加载.连接.初始化 1.加载:就是将class文件加载到内存.详细的说是,将class文件加载到运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封 ...

随机推荐

  1. poj3692 最大点权独立集/最大独立集

    题意:有男孩和女孩,男孩之间全部认识,女孩之间全部认识,一部分男孩和女孩认识,现在希望选出一些孩子,这些孩子都相互认识. 方法:正的做不好做,观察他的补图,补图之间无关系的边就是原图有关系的.补图中的 ...

  2. Lucene 4.7 --创建索引

    Lucene的最新版本和以前的语法或者类名,类规定都相差甚远 0.准备工作: 1). Lucene官方API http://lucene.apache.org/core/4_7_0/index.htm ...

  3. spring - ioc和aop

    1.程序中为什么会用到spring的ioc和aop 2.什么是IOC,AOP,以及使用它们的好处,即详细回答了第一个问题 3.原理 关于1: a:我们平常使用对象的时候,一般都是直接使用关键字类new ...

  4. 【poj2546】 Circular Area

    http://poj.org/problem?id=2546 (题目链接) 题意 求两圆的面积交 Solution 一道水题Wa死我了,肯定是昨晚搞太晚的缘故= =. 两圆的位置关系有5种,而这里要求 ...

  5. SQLServer错误:过程 sp_addextendedproperty,第 xxx 行对象无效。'dbo.xxx.xxx' 不允许有扩展属性,或对象不存在。

    上传数据库到虚拟主机,在执行SQL脚本的时候出现以下的错误: 消息 15135,级别 16,状态 8,过程 sp_addextendedproperty,第 37 行 对象无效.'dbo.Messag ...

  6. Java Web 设置默认首页

    一.问题描述 这里所谓的默认首页,是指在访问项目根目录时(如 http://localhost:8080/zhx-web/ )展示的页面,通过在web.xml里配置 <welcome-file- ...

  7. C文件操作(全)

    引用自:http://www.cnblogs.com/whiteyun/archive/2009/08/08/1541822.html 文件 文件的基本概念 所谓“文件”是指一组相关数据的有序集合. ...

  8. 织梦DedeCMS删除所有栏目或文章后,新建ID不从1开始的解决方法

    这个修改方法很简单,从模板无忧那里找到的,只需要在后台系统-SQL命令行工具里面运行以下语句即可,不用采用笨方法重新安装织梦CMS了. 删除所有栏目,新建ID从1开始: ALTER TABLE `de ...

  9. 锋利的jQuery-4--动画方法总结简表

  10. Java-优秀博客推荐

    一. TCP/IP Socket 兰亭风雨的专栏: http://blog.csdn.net/ns_code 二. NIO 并发编程网-Java NIO系列教程:http://ifeve.com/ch ...