单例模式及常见写法分析(设计模式01)

保证一个类仅有一个实例,并提供一个该实例的全局访问点。

——《设计模式》

单例模式的概念很简单,下面以C#语言为例子,列出常见单例写法的优缺点。

1、简单实现

 public sealed class Singleton
    {
        static Singleton instance = null;

        public void Show()
        {
            Console.WriteLine(  "instance function");
        }
        private Singleton()
        {
        }

        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }

评注:

对于线程来说不安全
 单线程中已满足要求
优点:
由于实例是在 Instance 属性方法内部创建的,因此类可以使用附加功能
直到对象要求产生一个实例才执行实例化;这种方法称为“惰性实例化”。惰性实例化避免了在应用程序启动时实例化不必要的 singleton。

2、线程的安全

public sealed class Singleton
    {
        static Singleton instance = null;
        private static readonly object padlock = new object();

        private Singleton()
        {
        }

        public static Singleton Instance
        {
            get
            {
                lock (padlock)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }

                return instance;
            }
        }
    }

评注:

同一个时刻加了锁的那部分程序只有一个线程可以进入
对象实例由最先进入的那个线程创建
后来的线程在进入时(instence == null)为假,不会再去创建对象实例
增加了额外的开销,损失了性能

3、双重锁定

 public sealed class Singleton
    {
        static Singleton instance = null;
        private static readonly object padlock = new object();

        private Singleton()
        {
        }

        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (padlock)
                    {
                        if (instance == null)
                        {
                            instance = new Singleton();
                        }
                    }
                }
                return instance;
            }
        }
    }

评注:

多线程安全
线程不是每次都加锁
允许实例化延迟到第一次访问对象时发生

4、静态初始化

 public sealed class Singleton
    {
        private static readonly Singleton instance = null;
        static Singleton()
        {
            instance = new Singleton();
        }
        private Singleton()
        {
        }
        public static Singleton Instance
        {
            get
            {
                return instance;
            }
        }
    }

评注:

依赖公共语言运行库负责处理变量初始化
公共静态属性为访问实例提供了一个全局访问点
对实例化机制的控制权较少(.NET代为实现)
静态初始化是在 .NET 中实现 Singleton 的首选方法

小注:

静态构造函数既没有访问修饰符,C#会自动把他们标记为private,之所以必须标记为private,

是为了阻止开发人员写的代码调用它,对它的调用总是由CLR负责的。


5、延迟初始化

public sealed class Singleton
    {
        private Singleton()
        {
        }
        public static Singleton Instance
        {
            get
            {
                return Nested.instance;
            }
        }

        public static void Hello()
        {
        }

        private class Nested
        {
            internal static readonly Singleton instance = null;
            static Nested()
            {
                instance = new Singleton();
            }
        }
    }

评注:

初始化工作由Nested类的一个静态成员来完成,这样就实现了延迟初始化。

由于静态函数的调用时机,是在类被实例化或者静态成员被调用的时候进行调用,并且是由.net框架来调用静态构造函数来初始化静态成员变量, 所以,如果按照写法四来写,再调用Hello方法的时候,就会实例化出来Singleton实例,这不是我们想看到的,因为我们有可能只是想用Hello方法,而不是别的。

注意事项:

1、Singleton模式中的实例构造器可以设置为protected以允许子类派生。
2、Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。
3、Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。
4、Singletom模式只考虑到了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收的平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。

总结:

1、Singleton模式是限制而不是改进类的创建。
2、理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的构造器的任意调用”。
3、可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的。

作者:jiankunking 出处:http://blog.csdn.net/jiankunking

本文部分内容来自网络,截图部分来自《CLR.via.C#第三版》

时间: 2024-10-06 22:21:10

单例模式及常见写法分析(设计模式01)的相关文章

SQL Server 存储过程的几种常见写法分析,我们该用那种写法

本文出处: http://www.cnblogs.com/wy123/p/5958047.html 最近发现还有不少做开发的小伙伴,在写存储过程的时候,在参考已有的不同的写法时,往往很迷茫,不知道各种写法孰优孰劣,该选用那种写法,以及各种写法优缺点,本文以一个简单的查询存储过程为例,简单说一下各种写法的区别,以及该用那种写法专业DBA以及熟悉数据库的同学请无视. 废话不多,上代码说明,先造一个测试表待用,简单说明一下这个表的情况 类似订单表,订单表有订单ID,客户ID,订单创建时间等,查询条件是

SQL Server 存储过程中处理多个查询条件的几种常见写法分析,我们该用那种写法

本文出处: http://www.cnblogs.com/wy123/p/5958047.html 最近发现还有不少做开发的小伙伴,在写存储过程的时候,在参考已有的不同的写法时,往往很迷茫,不知道各种写法孰优孰劣,该选用那种写法,以及各种写法优缺点,本文以一个简单的查询存储过程为例,简单说一下各种写法的区别,以及该用那种写法专业DBA以及熟悉数据库的同学请无视. 废话不多,上代码说明,先造一个测试表待用,简单说明一下这个表的情况 类似订单表,订单表有订单ID,客户ID,订单创建时间等,查询条件是

iOS.常用设计模式.01.单例模式

使用单例模式的类: UIApplication UIAccelerometer NSUserDefaults NSNotificationCenter NSFileManager NSBundle等 Singleton.h #import <Foundation/Foundation.h> @interface Singleton : NSObject // 始终返回同一个Singleton的指针 + (Singleton *)sharedManager; @property (strong,

企业架构分析&设计模式 课程

高焕堂的招牌课程 企业架构分析.设计模式和App Framework/SDK开发方法 by 高焕堂 亚太地区Android技术大会 主席 洞庭国际智能硬件检测基地 & 中云企业大数据中心(IDC) 首席架构师 微博:@高焕堂_台北                                课程简介: 本课程依据企业软件开发流程里的先后环节来作教学.主要目标在于介绍和阐述各环节的思想.模式.技术和实践要点.让学员能熟悉当今云计算&大数据潮流下,终端与云端的(业务)架构分析.API设计.框

IIFE的形式、原理和常见写法

IIFE: (immediately invoked function expression) 立即调用的函数表达式 因为在es6提出块作用域之前,js只有全局作用域global scope和函数作用域function scope. IIFE的目的是为了隔离作用域,防止污染全局命名空间. 意思就是,想隔离谁(变量.函数),就把定义它的这段代码装到一个function里. 因此经常会见到只出现一次的function. 而一般我们封装函数的目的是为了重复多次地调用. 为了实现作用域的隔离这么做,有违

设计模式01

设计模式01 Table of Contents 1 设计模式 1.1 基本原则 1.2 开-闭原则 1.2.1 与其他原则关系 1 设计模式 1.1 基本原则 系统的可扩展性由开-闭原则.里氏代换原则.依赖倒转原则.组合/聚合复用原则保证:系 统的灵活性由开-闭原则.迪米特原则.接口隔离原则保证:系统的可插入性由开-闭原 则.里氏代换原则.依赖倒转原则.组合/聚合复用原则保证. 当一个软件复用有道.易于维护,新功能加入到系统,或修改一个已有的功能将是容易 的,因此,代码高手就没有用武之地:而当

【网络安全】PHP常见漏洞分析

漏洞的形成原因复杂,有程序员编码的问题, 有系统的问题,还有可能是配置环境的问题.这里简单总结一下php的常见漏洞,让大家对网站漏洞有一个简单的认识. 如果想要快速入门,推荐大家可以观看本人精心制作的 PHP网站漏洞挖掘课程: PHP漏洞挖掘(二):PHP常见漏洞分析 0x01 sql注入漏洞 sql注入漏洞,只要是一个懂编程的基本都听说过的,即便你不太了解网络安全,这个漏洞也被大家广泛的知道了,因为它的危害性和影响的深远性. sql注入可以按照接收的元素分为 数字型注入和字符型注入.按照注入的

设计模式01: Singleton 单例模式

Singleton 单例模式 动机(Motivation)当进行软件开发是会有这样一种需求:在系统中只有存在一个实例才能确保它们的逻辑正确性.以及良好的效率.这应该是类设计者的责任,而不是使用者的责任. 意图(Intent)保证一个类仅有一个实例,并提供一个该实例的全局访问点.——<设计模式>GoF 单线程Singleton模型实现: 1 pulic class Singleton 2 { 3 private static Singleton instance;//如果客户不需要这个实例最好不

单例模式的几种常见写法

第一种:最简单的写法,缺点在于实例在类初始化的时候就创建了,如果在整个项目中都没有使用到该类,就会创建内存空间的浪费. public class Singleton { private Singleton(){} private static Singleton instance = new Singleton(); public static Singleton getInstance(){ return instance; } } 第二种:解决了写法一在类初始化的时候就创建实例的问题,然而只