设计模式学习 之 单例模式

单例模式: 定义 一个类有且仅有一个实例,并且自行实例化向整个系统提供。

《来自百科》 这些 概念和要点 是 了解 单例模式的 一些基本概念

C# 单例实现要点

Singleton模式是限制而不是改进类的创建。

Singleton类中的实例构造器可以设置为Protected以允许子类派生。

Singleton模式一般不要支持Icloneable接口,因为这可能导致多个对象实例,与Singleton模式的初衷违背。

Singleton模式一般不要支持序列化,这也有可能导致多个对象实例,这也与Singleton模式的初衷违背。

Singleton只考虑了对象创建的管理,没有考虑到销毁的管理,就支持垃圾回收的平台和对象的开销来讲,我们一般没必要对其销毁进行特殊的管理。

理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的构造器的任意调用”。

可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的

优点

实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例

灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程

缺点

开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题,上面的五种实现方式中已经说过了。

可能的开发混淆:使用 singleton 对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用 new 关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。

对象的生存期:Singleton 不能解决删除单个对象的问题。在提供 内存管理 的语言中(例如基于 .NET Framework 的语言),只有 Singleton 类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除

对象实例,但这样会导致 Singleton 类中出现悬浮引用。

适用性

当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。

当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

 private static Singleton instance;

       /// <summary>
       /// 把构造函数 声明 为 私有,这样就 阻止了 外界 对 这个类的new 操作
       /// </summary>
       private Singleton()
       {     

       }

       //此方法是获得 本类 实例 的 全局 唯一的访问点
       public static Singleton GetInstance()
       {

           if (instance == null)
           {

               instance = new Singleton();

           }

           return instance;

       }

    }

但 上面代码 在 多线程程序中, 多个线程同时访问getinstance();就可能造成创建 多个 实例。所以此时给进程 加一把锁 lock 来进行处理。

Lock 是确保 当一个线程 位于代码 的临界区时,另一个线程 不能进入临界区。如果其他线程 试图进入 临界区 ,则会 一直 处于 等待状态,知道 对象会被释放。

修改代码:

 public   class Singleton
    {
       private static Singleton instance;

       // 创建一个 静态只读的 进程 辅助对象

       private static readonly object syncroot = new object();
       /// <summary>
       /// 把构造函数 声明 为 私有,这样就 阻止了 外界 对 这个类的new 操作
       /// </summary>
       private Singleton()
       {     

       }

       //此方法是获得 本类 实例 的 全局 唯一的访问点
       public static Singleton GetInstance()
       {

           //在同个 时刻,加入锁的 那部分程序 只有一个线程可以进入
           lock (syncroot)
           {
               if (instance == null)
               {

                   instance = new Singleton();

               }

           }
           return instance;

       }

    }

不直接 lock (instance) 是因为 不知道 有没有创建过实例,所以只能 在 getinstance()时 加锁。

但是每次 调用 getinstance()时都要 进行 lock() 不好,所以应该在必要时进行lock();

引入双重锁定

  public   class Singleton
    {
       private static Singleton instance;

       // 创建一个 静态只读的 进程 辅助对象

       private static readonly object syncroot = new object();
       /// <summary>
       /// 把构造函数 声明 为 私有,这样就 阻止了 外界 对 这个类的new 操作
       /// </summary>
       private Singleton()
       {     

       }

       //此方法是获得 本类 实例 的 全局 唯一的访问点
       public static Singleton GetInstance()
       {
           //先判断 实例是不是存在, 不存在 再 加锁 锁定 一个 线程
           if (instance == null)
           {
               //在同个 时刻,加入锁的 那部分程序 只有一个线程可以进入
               lock (syncroot)
               {

                  //此时的 判断实例是不是为空 是 当 有两个 进程 AB 依次执行时, A执行完后 接着 执行B
                   // 因为没有 实例的释放, 要进行 再次 判空 看是否已经 有实例产生了,
                   // 这样 防止了产生多个实例
                   if (instance == null)
                   {

                       instance = new Singleton();

                   }

               }
           }
               return instance;

       }

    }

在实际的开发中 C# 与 公共 语言运行库 提供了 一种 静态 初始化 的 方法,这种方法不需要开发人员 显示的 编写线程安全代码 ,即可 解决多线程环境下不安全的

问题

  public sealed class Singleton
   {
       //在第一次引用类的任何成员创建实例 公共语言运行库 负责处理变量初始化

       private static readonly Singleton instance = new Singleton();

       public static Singleton getinstance()
       {

           return instance;
       }

   }

由于这种方法  是在 自己 被加载时 就将自己 实例化, 所以形象的称为“ 饿汉式” 单例类  由于一加载就实例化 提前占用系统资源

前面 处理方式 是在 自己 第一次 被 引用时 才 实例化,所以称为“懒汉式 ” 单例类。 面临的更多是多线程 安全 问题 ,需要双向 锁定 才能解决

全局变量 和 单例 模式 的 区别

全局变量 即对一个对象的静态引用,全局变量确实可以提供单例模式实现的全局访问这个功能,但是,它并不能保证您的应用程序中只有一个实例,同时,在编码规范中,也明确指出,应该要少用全局变量,因为过多的使用全局变量,会造成代码难读,还有就是全局变量并不能实现继承(虽然单例模式在继承上也不能很好的处理,但是还是可以实现继承的)而单例模式的话,其在类中保存了它的唯一实例,这个类,它可以保证只能创建一个实例,同时,它还提供了一个访问该唯一实例的全局访问点。

时间: 2024-10-15 16:06:27

设计模式学习 之 单例模式的相关文章

【我的设计模式学习】单例模式

单例模式大概是最直观的一种设计模式了.尽管直观却不简单. 数学与逻辑学中,singleton定义为"有且仅有一个元素的集合".单例模式可以如下定义:"一个类有且仅有一个实例,并且自行实例化向整个系统提供". 我比较喜欢Design Patterns 一书中的描述"保证一个类仅有一个实例,并提供一个访问它的全局访问点". 单例模式的特点 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例

设计模式学习01—单例模式

一.动机与定义 系统中有些资源只能有一个,或者一个就够,多个浪费.例如一个系统只能有一个窗口管理器或文件系统.一个系统只能有一个计时器或序号生成器.web系统只能有一个页面计数器等等.此时,最好就需要把这些资源设置成有且仅有一个实例. 代码中也就是如何保证一个类只有一个实例并且这个实例能够被访问呢?只有一个实例的就意味着不能让其他类来实例化,也就是只能自己实例化自己.能够被访问也就意味着自身要对外提供全局方法来获取到这个实例,这就是单例模式. 单例模式定义:确保某一个类只有一个实例,而且自行实例

Java设计模式学习01——单例模式(转)

原地址:http://blog.csdn.net/xu__cg/article/details/70182988 Java单例模式是一种常见且较为简单的设计模式.单例模式,顾名思义一个类仅能有一个实例,并且向整个系统提供这一个实例. 单例模式的特点: 单例类仅能有一个实例. 单例类必须为自己创建实例. 单例类必须向外界提供获取实例的方法. 以下是几种实现方法 一.懒汉式单例(能够延时加载) public class SingleTon { private static SingleTon ins

C#设计模式学习笔记-单例模式

最近在学设计模式,学到创建型模式的时候,碰到单例模式(或叫单件模式),现在整理一下笔记. 在<Design Patterns:Elements of Resuable Object-Oriented Software>中的定义是:Ensure a class only has one instance,and provide a global point of access to.它的主要特点不是根据客户程序调用生成一个新的实例,而是控制某个类型的实例数量-唯一一个.(<设计模式-基于C

【C++深入浅出】设计模式学习之单例模式

但凡成为大家公认的模式,都是有一些不可小觑的威力,今天分享一个简单的设计模式:单例模式. 单例模式用于一些只希望有一个实例的类或者只希望执行一次的操作:校长只能有一个.老板只能有一个.用户点击弹窗只希望弹出一次.用全局变量等方式也可以实现,但是多了很多判断和处理代码,并且职责模糊,类的唯一实例化是交给调用者进行判断处理的,每调用一次就要做一次判断,重复了很多工作量,如果是多线程编程,不好的同步设计更是会导致程序卡顿. 如果还在为这些重复工作苦恼,是时候着手单例模式了:设计简单.调用方便.一劳永逸

设计模式学习系列——单例模式

单例模式 单例模式(Singleton Pattern),在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例.即一个类只有一个对象实例. 优点:1)在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如首页页面缓存). 2)避免对资源的多重占用(比如写文件操作). 缺点:违背了"单一职责原则",该类既是工厂又是产品(自己创建了自己): 从具体实现角度来说,就是以下三点: 一是单例模式的类只提供私有的构造函数, 二

Java设计模式学习记录-单例模式

前言 已经介绍和学习了两个创建型模式了,今天来学习一下另一个非常常见的创建型模式,单例模式. 单例模式也被称为单件模式(或单体模式),主要作用是控制某个类型的实例数量是一个,而且只有一个. 单例模式 单例模式的实现方式 实现单例模式的方式有很多种,大体上可以划分为如下两种. 外部方式 在使用某些全局对象时,做一些“try-Use”的工作.就是如果要使用的这个全局对象不存在,就自己创建一个,把它放到全局的位置上:如果本来就有,则直接拿来使用. 内部实现方式 类型自己控制正常实例的数量,无论客户程序

设计模式学习之单例模式

一.单例模式实现方式 常见的 1.饿汉方式 示例代码: package com.mt.singleton;/** * 设计模式单例模式之饿汉实现方式 * 线程安全,调用效率高,但无法实现延迟加载 * @author MT * */public class SingletonDemo1 { private static SingletonDemo1 s = new SingletonDemo1(); //私有化构造器 private SingletonDemo1(){   } //添加获取对象的公

php设计模式学习(单例模式和观察者模式)

1.单例模式 前几天跟一个朋友讨论的时候,朋友提了一个问题,为什么所有类不都用单例模式,都用单例模式真的是最好的吗? php中不管是new出来的对象还是静态变量,只对本次请求有效,当一次请求结束的时候,所有的对象和变量都会被销毁. 当一个对象每次请求只用一次的时候,单例模式和直接new没什么区别吧. 另一点,当一个对象涉及较多的属性修改或设置,又需要多次使用,很多时候可能我们更希望每次都进行初始化,而不是直接使用一个不知道被做了哪些操作的对象 综上,个人认为,单例模式更适用于一次请求需要多次使用