单例模式的定义:

确保一个类只有一个实例,并提供一个全局访问点。

首先实例大家应该都明白就是类生成对象的过程简单的就是String s=new String(),则s就是个实例。

Q:如何只生成一个实例?

A:1)首先必须将构造函数变为私有从而防止其他类实例化,并且只能有一个构造函数。因为系统会默认一个无参构造函数,而且默认public访问修饰符。 所以必须写一个私有无参让默认无效。(通常单例模式都是不带形参的)

2)在该类中声明一个自己本身的静态实例,然后通过静态方法返回。

Q:如何提供一个全局访问点?

A:在类中创建一个公共并且静态的属性。(因为静态方法是类中的一个成员方法,属于整个类,即不用创建任何对象也可以直接调用。单例模式是不允许其他类实例的。)

代码:

分为两种模式:

1.LAZY模式

就是延迟加载, 设计模式是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据(读取属性值)的时候,才真正执行数据加载操作.有效使用它可以大大提高系统性能。

2.饿汉模式

与LAZY模式相反 ,加载时会将自己实例化。起来最容易的单例模式。

分析代码1:(经典)

  // 不要用这种方式

  public sealed class Singleton
  {
      private static Singleton instance=null;//声明自己本身的静态实例
      private Singleton(){}//私有构造
      public static Singleton Instance() //提供全局访问点
      {
              if (instance==null)//实例不存在则创建
              {
                 instance = new Singleton();
             }
             return instance;
     }
 }

该代码仅供理解,单例模式的定义。

问题:该方法是非线程安全的,当有两个线程同时进入时,如果instance为null则都会创建实例。实际上,在测试以前,实例就已经有可能被创建了,但是内存模型不能保证这个实例能被其他的线程看到。

下面我们优化改进

分析代码2:(非安全线程)

public sealed class Singleton
{
    private static Singleton instance = null;
    private static readonly object padlock = new object();//定义一个标识确保线程同步
    Singleton(){}
    public static Singleton Instance()
    {
            lock (padlock)//线程到达时加锁 运行完之后解锁 当遇到加锁线程就会挂起等待解锁
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
    }
}

以上解决了多线程问题。

问题:性能上来说,锁变成了每次都必须的当这个实例被响应的时候。此时完全没必要对线程辅助对象加锁之后再去判断,所以上面的实现方式增加了额外的开销。

下面我们进行优化改进:

 代码分析3:(双重锁定)

  public sealed class Singleton
  {
      private static Singleton instance = null;
      private static readonly object padlock = new object();
      Singleton(){}
      public static Singleton Instance
      {
          get
          {
             if (instance == null)//外层的if语句块,这使得每个线程欲获取实例时不必每次都得加锁,因为只有实例为空时(即需要创建一个实例),才需加锁创建
             {
                 lock (padlock)
                 {
                     if (instance == null)
                     {
                         instance = new Singleton();
                     }
                 }
             }
             return instance;
         }
     }
 }

这种“双重检查锁定”理论上是完美的

问题是:并不能保证它会在单处理器或多处理器计算机上顺利运行。(反正就是有问题吧 之后再研读一下 看看具体是怎么回事)

代码分析4:(不完全LAZY)

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

      // 显示的static 构造函数
      //静态构造函数抑制了beforefieldinit 特性(访问成员之前就执行静态函数)
      static Singleton(){}
      private Singleton(){}
      public static Singleton Instance
     {
         get
         {
             return instance;
         }
     }
 }

不完全LAZY模式(通过抑制beforefildinit特性并不能起到太大的效果)

代码分析5:(完全LAZY)

  public sealed class Singleton
  {
      private Singleton(){}
      public static Singleton Instance { get { return Nested.instance; }}
  //嵌套类
      private class Nested
      {
         //抑制beforefieldinit特性
          static Nested(){}
         internal static readonly Singleton instance = new Singleton();
     }
 }

这里使用了嵌套类(嵌套类型是LAZY加载的,也就是说嵌套类型在使用他时才会初始化)

代码分析6:(Lazy<T>)

 public sealed class Singleton
 {
 //使用.NET4 Lazy<T>
     private static readonly Lazy<Singleton> lazy =new Lazy<Singleton>(() => new Singleton());
     public static Singleton Instance { get { return lazy.Value; } }
     private Singleton() {}
 }

Lazy<T> 对象初始化默认是线程安全的,在多线程环境下,第一个访问 Lazy<T> 对象的 Value 属性的线程将初始化 Lazy<T> 对象,以后访问的线程都将使用第一次初始化的数据。

有关Lazy<T>介绍:延迟实例化 Lazy

以上全部是LAZY模式,现在了解下饿汉模式

代码分析7:

public sealed class Singleton
{
        private static readonly Singleton instance=new Singleton();//直接实例化
        private Singleton(){}
        public static Singleton Instance()
        {
               return instance;
        }
}

在这种模式下,无需自己解决线程安全性问题,CLR会给我们解决。由此可以看到这个类被加载时,会自动实例化这个类,而不用在第一次调用Instance()后才实例化出唯一的单例对象。

为了优化系统当然还是选择优化模式。LAZY模式最好的应该是使用Lazy<T>简短安全。

以上都是我在博客园对单例模式学习的总结。今后会补充一些具体的项目中的案例让和我一样的新手更容易吸收理解最终达到举一反三。这里重点参考了这里的文章,希望大家有指教的地方多多提点。感谢。

C# 单例模式(Singleton Pattern)(转SuagrMatl)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. Net设计模式实例之单例模式( Singleton Pattern)

    一.单例模式简介(Brief Introduction) 单例模式(Singleton Pattern),保证一个类只有一个实例,并提供一个访问它的全局访问点.单例模式因为Singleton封装它的唯 ...

  9. 深入设计模式(二)——单例模式(Singleton Pattern)

    一.单例模式介绍 单例模式(Singleton Pattern),保证一个类只有一个实例,并提供一个访问它的全局访问点.单例模式因为Singleton封装它的唯一实例,它就可以严格地控制客户怎样访问它 ...

  10. 设计模式系列之单例模式(Singleton Pattern)

    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式.这种模式涉及到一个单一的类,该类负责创建自己的对象 ...

随机推荐

  1. 8.Spark SQL

    Spark SQL 1 Why Apache Spark 2 关于Apache Spark 3 如何安装Apache Spark 4 Apache Spark的工作原理 5 spark弹性分布式数据集 ...

  2. [Tyvj 1728] 普通平衡树

    大名鼎鼎的板子题w 照例先贴题面 Describtion 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. ...

  3. iOS Socket 整理以及CocoaAsyncSocket、SRWebSocket源码解析(一)

    写在准备动手的时候: Socket通讯在iOS中也是很常见,自己最近也一直在学习Telegram这个开源项目,Telegram就是在Socket的基础上做的即时通讯,这个相信了解这个开源项目的也都知道 ...

  4. C++ STL list详解

    一.解释: list是一种序列式容器.list容器完成的功能实际上和数据结构中的双向链表是极其相似的,list中的数据元素是通过链表指针串连成逻辑意义上的线性表,list不仅是一个双向链表,而其还是一 ...

  5. ASP.NET Core MVC – Caching Tag Helpers

    简介 缓存可以大大提高应用程序加载时间和响应速度.我们可以使用缓存Tag Helpers缓存不会频繁更改的HTML内容. 在上一篇文章中,我们谈到了Tag Helpers,演示Tag Helpers能 ...

  6. swift UILabel多行显示时 计算UILable的高度(可用于UILable高度自适应)

    代码如下 func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{ let label:UILabel = ...

  7. hdu--1711--kmp应用在整形数组--Number Sequence

    /* Name: hdu--1711--Number Sequence Author: shen_渊 Date: 16/04/17 19:58 Description: 第一次知道,KMP能用在整形数 ...

  8. 计算机四级网络工程师--《操作系统(Operating System)》重点内容学习

    开篇语 今天开始看<操作系统>,没办法,计算机网络技术还算有点底子.至于操作系统要不是以前看过一些这方面的书籍,以及上学期学了单片机工作原理,我估计我真的是懵逼的!所幸,在网上找的233网 ...

  9. 【学习OpenCV】——2.4对图像进行平滑处理

    作者基于WIN10+VS2015+OpenCV3.0.0 (本人在学习的时候参考了xiahouzuoxin 的有关文章,在此感谢 ) 图像平滑与图像模糊是同一概念,主要用于图像的去噪.平滑要使用滤波器 ...

  10. Android Gesture 手势创建以及使用示例

    在Android1.6的模拟器里面预装了一个叫Gestures Builder的程序,这个程序就是让你创建自己的手势的(Gestures Builder的源代码在sdk问samples里面有,有兴趣可 ...