zoukankan      html  css  js  c++  java
  • Singleton patterns 单件(创建型模式)

    1、模式分类

         1.1  从目的来看:

                        •      – 创建型(Creational)模式:负责对象创建。

                        •      – 结构型(Structural)模式:处理类与对象间的组合。

                        •      – 行为型(Behavioral)模式:类与对象交互中的职责分配。

         1.2 从范围来看:

                        •     – 类模式处理类与子类的静态关系。

                        •     – 对象模式处理对象间的动态关系。

    2、动机(Motivation)目的  

                        在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。

    3、意图(Intent)             

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

                                                                                              ——《设计模式》GoF

    4、单例模式多种实现方法

        4.1 单线程Singleton 模式实现

     1  class Singleton
     2     {
     3         private static Singleton instance;   
     4         private Singleton() //防止外界随意new此对象,如果访问级别设置成protected,那么子类可以派生,同时也也不可以实例化此对象
     5         {         
     6         }
     7         public static Singleton Instance
     8         {
     9             get {
    10                 if (instance == null)  //起到延迟加载对象的作用,当用户用不到此实例的时候
    11                 {
    12                     instance = new Singleton();
    13                 }
    14                 return instance;
    15             }
    16         }
    17     }

    单线程Singleton模式的几个要点
                      • Singleton模式中的实例构造器可以设置为protected以允许子类派生。(同样不可实例化对象,受保护级别限制)
                      • Singleton模式一般不要支持ICloneable接口(实例克隆),因为这可能会导致多个对象实例,与Singleton模式的初衷违背。(实现了ICloneable接口,就必须实现Clone()方法,在此方法中我们可以返回新的对象,这样就与Singleton模式相违背了!)
                      • Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。(构造对象的方式:可以通过构造器,也可以通过序列化构造对象,序列化出来的对象和原来的对象地址是不一样的,是完全的深拷贝方式(创建新的对象))
                      • Singletom模式只考虑到了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收的平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。
              (缺点)• 不能应对多线程环境:在多线程环境下,使用Singleton模式仍然有可能得到Singleton类的多个实例对象。(在上面的代码第10行进行if判断的时候,假设现在有两个线程(A,B)同时执行到了此行,当A线程进行if判断,此时判断为null,就去实例化对象,但是A线程还没来得及进行对象的实例化的时候,此时B线程就进行了if的判断,并完成了对此对象的判断,判断为null,所以B线程就会去创建另一个实例,所以就创建了两个实例!)

        4.2、多线程Singleton 模式实现

     1 class Singleton
     2     {
     3         private static volatile Singleton instance = null; //volatile(编译器在对代码进行编译的时候,会对代码进行一些微调,对代码的顺序进行调整,
    volatile关键字就保证了编译器不会对instance进行代码的微调,
    这样就保证了严格意义上的多线程不会出现创建出多个实例的情况)
    4 private static object lockHelper = new object(); //辅助器 5 private Singleton() //防止外界随意new此对象 6 { 7 } 8 public static Singleton Instance 9 { 10 get 11 { 12 if (instance == null) 13 { 14 lock (lockHelper) 15 { 16 if (instance == null)//双检查 17 { 18 instance = new Singleton(); 19 } 20 } 21 } 22 return instance; 23 } 24 } 25 }

    优缺点:这种实现方式对多线程来说是安全的,同时线程不是每次都加锁,只有判断对象实例没有被创建时它才加锁(如果最外层的if不加的话,那么其他线程都会进行加锁操作,会增加额外的开销,损失性能),加锁后还得再进行对象是否已被创建的判断。它解决了线程并发问题,同时避免在每个 Instance 属性方法的调用中都出现独占锁定。它还允许您将实例化延迟到第一次访问对象时发生。

    volatile:

    MSDN上的解释:volatile 关键字表示字段可能被多个并发执行线程修改。声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。这样可以确保该字段在任何时间呈现的都是最新的值

         4.3、 使用.NET类型初始化机制实现多线程Singleton 模式(最好的方式)

    1    sealed class Singleton
    2     {
    3         private static readonly Singleton instance = new Singleton();
    4         private Singleton() //防止外界随意new此对象
    5         {
    6         }
    7     }

    其实上面的代码实现如果展开来的话等同于下面代码的实现

     1   sealed class Singleton
     2     {
     3         private static readonly Singleton instance;
     4         static Singleton() //在调用instance静态字段时会先去执行此静态构造器,静态构造器能保证多线程环境下只有一个线程执行了此静态构造器,为我们自动加锁
     5         {                  
     6             instance = new Singleton();//在静态构造器中实例化
     7         }
     8         private Singleton() //防止外界随意new此对象
     9         {
    10         }
    11     }

    该类标记为 sealed 以阻止发生派生,而派生可能会增加实例。此外,变量标记为 readonly,这意味着只能在静态初始化期间(此处显示的示例)或在类构造函数中分配变量。

    缺点:

    • 我们对实例化机制的控制权较少!在4.1和4.2中能够在实例化之前使用非默认的构造函数或执行其他任务。由于在此实现方法中由 .NET Framework负责执行初始化,因此您没有这些选项。
    • 无法实现延迟初始化,
    • 4.3的实现方法无法进行传参,4.1和4.2的实现方式都可以进行传参,主要是因为对象的实例化是在方法内部创建的(属性实质为方法),所以我们可以把属性写成带参数的方法即可!如下,对4.1方法变为带参数的!
     1  class Singleton
     2     {
     3         private static Singleton instance;
     4         public string Name { get; set; }
     5         public int Age { get; set; }
     6         public static Singleton GetInstance(string name, int age)
     7         {
     8             if (instance == null)
     9             {
    10                 instance = new Singleton(name, age);
    11             }
    12             return instance;
    13         }
    14         private Singleton(string name, int age)
    15         {
    16             this.Name = name;
    17             this.Age = age;
    18         }
    19     }

    5、延迟初始化

     1 public sealed class Singleton
     2  {
     3      Singleton()
     4      {
     5      }  
     6      public static Singleton Instance
     7      {
     8          get
     9         {
    10             return Nested.instance;
    11         }
    12      }    
    13     class Nested
    14     {
    15         static Nested()
    16         {
    17         }
    18        internal static readonly Singleton instance = new Singleton();
    19     }
    20 }

     这里,初始化工作有Nested类的一个静态成员来完成,这样就实现了延迟初始化,并具有很多的优势,是值得推荐的一种实现方式 

    6、Singleton模式扩展
                • 将一个实例扩展到固定几个实例,例如对象池的实现。这样做是允许的而且是有意义的!
                • 将new 构造器的调用转移到其他类中,例如多个类协同工作环境中,某个局部环境只需要拥有某个类的一个实例。
                • 理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的实例构造器的任意调用”。 

     7、.NET框架中的Singleton应用

    • winform程序,你只需要点击按钮,弹出一个窗口,并且保证此窗口只能有一个!再点击按钮是无法在弹出此窗体的!
    • PC机中可能有几个串口,但只能有一个COM1口的实例。
    • 系统中只能有一个窗口管理器。
    • .NET Remoting中服务器激活对象中的Sigleton对象,确保所有的客户程序的请求都只有一个实例来处理。

     8、推荐参考书
                • 《设计模式:可复用面向对象软件的基础》GoF                             --小白看起来会有点困难
                • 《面向对象分析与设计》Grady Booch                                       --翻译有些问题
                • 《敏捷软件开发:原则、模式与实践》Robert C. Martin
                • 《重构:改善既有代码的设计》 Martin Fowler
                • 《Refactoring to Patterns》Joshua Kerievsky                         --没中文版

     9、参考

        《C#面向对象设计模式纵横谈》    李建忠

         http://terrylee.cnblogs.com    TerryLee

     

                                                                                                      作者:MrZivChu

    2013-08-02 15:34:03

  • 相关阅读:
    实现翻页效果
    使用AHKActionSheet
    [翻译] GSProgressView
    [翻译] NSRegexTester
    下载时获取文件大小
    高级mask应用
    使用UILabel实现滚动字幕移动效果
    动画绘制水波纹
    能产生粒子效果的CAEmitterLayer
    使用UITableView实现图片视差效果
  • 原文地址:https://www.cnblogs.com/MrZivChu/p/Singleton_patterns.html
Copyright © 2011-2022 走看看