zoukankan      html  css  js  c++  java
  • 单例模式

    1.定义

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

      通常我们可以建立一个全局变量使得一个对象被多个类所访问,但是这样还是无法防止你多次实例化这个对象;这时候一个最好的方法就是:让类自身来负责保证他的唯一实例。这个类保证没有其他实例可以被创建,并且它可以提供一个访问自身实例的方法。

    2.理解

      单例模式因为由类自己封装了它的唯一实例,这样就可以严格的控制客户怎样访问它及何时访问它;简单的说就是实现对唯一实例的受控访问。

      同时也要区别单例模式下的类和普通实用类的区别:实用类不保存状态,只提供一些静态的属性和方法让你使用,而单例类是有状态的;实用类不能用于继承多态,而单例类却可以由子类来继承;实用类只不过是一些方法、属性的集合,而单例类是有着唯一的对象实例。在具体使用时,需要根据需求来确定到底使用哪一种方式。

    3.多线程下的单例模式

      在多线程下,为了保证仍然实现单例模式,需要给进程加一把锁来处理,即使用lock语句。

      lock的含义:lock是确保当一个线程位于代码的临界区域时,另一个线程不能进入临界区域。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止的意思),直到该对象区域被释放。具体代码如下:

     1 class Singleton
     2     {
     3         private static Singleton instance;
     4         //在程序运行时就创建一个静态只读的进程辅助对象[由于加锁时,程序是不知道instance有没有被创建过实例,
     5         //从而无法加锁,所以需要创建一个辅助对象]
     6         private static readonly object syncRoot = new object();
     7         private Singleton()
     8         {
     9 
    10         }
    11         /*下面这种方式,由于没有判断,会导致每一次调用此方法时都需要lock,因此会影响性能*/
    12         public static Singleton GetInstance1()
    13         {
    14             lock (syncRoot)
    15             {
    16                 if (instance == null)
    17                     instance = new Singleton();
    18             }
    19             return instance;
    20         }
    21 
    22         /*所以需要“双重锁定”来改善*/
    23         public static Singleton GetInstance2()
    24         {
    25             //第一个判断:实例是否存在,如果不存在则加锁处理
    26             if (instance == null)
    27             {
    28                 lock (syncRoot)
    29                 {
    30                     //第二次判断:这里是为了实现单利模式(如果没有这个判断,那么多线程下就不能保证单例了)
    31                     if (instance == null)
    32                         instance = new Singleton();
    33                 }
    34             }
    35             return instance;
    36         }
    37     }

    4.扩展

      在实际应用中,C#与公共语言运行库也提供了一种单例模式的实现“静态初始化”,这种方式不需要开发人员显式的编写线程安全代码,即可解决多线程环境下单例模式的安全问题。如下面代码所示:

     1 /*阻止派生发生,因为派生可能会产生多个实例*/
     2     public sealed class Singleton
     3     {
     4         /*在加载类时就将自己实例化,由公共语言运行库负责执行;但是因为instance被标记为了只读,所以只能在静态初始化期间或者
    在类的构造函数中分配变量
    */ 5 private static readonly Singleton instance = new Singleton(); 6 private Singleton() 7 { } 8 public static Singleton GetInstance() 9 { 10 return instance; 11 } 12 }

    由这种方式又引出两种单例模式:

      饿汉式单例:由于这种方式下(静态初始化的方式),实在类自己被加载时就将自己实例化,所以被形象的成为饿汉式单例。

      懒汉式单例:在类被第一次引用时才会将自己实例化。

      区别:饿汉式单例由于在类加载时就已经实例化,因此会提前占用系统资源;而懒汉式又需要开发人员自己处理多线程环境下的安全问题,需要做双重锁定才可以保证安全。正常情况下,饿汉式单例已经可以满足我们的需求。

    5、我的浅薄理解

      我的使用环境是:在一个窗体程序中,需要一个单独的类来记录一些环境状态(数据库连接、中间结果等),这就需要保证这个记录环境的类只能被实例化一次,然后其他类在使用时才可以访问已经保存的变量,所以用到了单例模式。通过一次使用下来我觉得,懒汉式的单例模式更加容易理解,还有就是因为我的程序是单线程的环境,并且要在不同的地方给环境变量赋值,所以觉得饿汉式单例的话变量没法赋值了,因此使用的是懒汉式单例模式(斯以为这种方式看起来也更加顺眼)。所以我的不成熟意见还是认为懒汉式单例更加易用一些。

  • 相关阅读:
    数据挖掘读书笔记-数据库系统技术
    数据挖掘读书笔记-典型的数据挖掘系统
    数据挖掘读书笔记-数据挖掘的概念
    数据产品经理做什么?
    从浏览器渲染的角度谈谈html标签的语义化
    Mozilla推动互联网成为游戏发展的强有力平台
    css知识点
    css变形 transform
    跟css背景有关的属性
    css颜色表示的方式
  • 原文地址:https://www.cnblogs.com/qingtian-jlj/p/5990540.html
Copyright © 2011-2022 走看看