单例模式

来源:互联网 发布:山西太原理工软件学院 编辑:程序博客网 时间:2024/06/03 17:18

创建型模式除了工厂家族还有三种:单例模式,原型模式,建造者模式,这次就来总结一下最简单的单例模式

单例模式

 定义

   (Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点


 UML结构



Singleton类的代码


<span style="font-size:18px;">class Singleton  {      private static Singleton instance;//声明静态变量        private Singleton ()  //因为是静态方法,外部不能用new来实例化他      { }        public static Singleton GetInstance() //作用返回一个类实例,机制:做有无实例化判断,      {                                               if(instance==null)                //如果没有实例化过,          {              instance = new Singleton();   //由调用private的构造方法new出实例          }          return instance;               //如果实例化过了,则不再实例化,直接返回这个类的实例化对象      }    } </span>


应用场景

  • (1) 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器或资源管理器,或者需要考虑资源消耗太大而只允许创建一个对象。
  • (2) 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。

优缺点

  • 优点:单例模式提供了对唯一对象的受控访问;只有一个对象,节约资源;
  • 缺点:没有抽象层,扩展困难;违背单一职责原则;

 注意的地方

      在多线程的程序中,多个线程同时访问Singleton类,调用GetInstance()方法,会有可能创建多个实例。这就需要给进程加一把锁,因为前一阵刚经历过自考,在数据库中也涉及到锁的概念,所以这个概念并不陌生。那个是给事务中的进程加锁,和这里的概念大同小异。


lock:确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则他将一直等待(即被阻止),直到改对象被释放


<span style="font-size:18px;">        private static Singleton instance;          private static readonly object syncRoot = new object(); //程序运行时创建一个静态只读的进程辅助对象,因为不                                                                 // 知道有无实例对象,                                                                  //所以不能直接LOCK          private Singleton()           { }            public static Singleton GetInstance()           {              lock (syncRoot)         //在同一时刻加了锁的那部分程序只有一个线程可以进入              if (instance == null)                              {                  instance = new Singleton();                 }              return instance;                         } </span>


缺点:每次调用GetInstance()方法都得先lock,这样会影响性能,所以出现了双重锁定的方法,即先判断有无实例化对象,没有的话就执行Lock ,有的话直接返回对象


<span style="font-size:18px;">public static Singleton GetInstance()          {             if(instance ==null)             {                 lock (syncRoot)                 {                     if (instance == null)                     {                         instance = new Singleton();                     }                 }             }             return instance;                        }</span>



遗留的问题:关于饿汉懒汉单例类理解的不到位,看了看刘伟大牛写的二者比较的文章,有了点思路。



上述加锁过程都是懒汉式单例类,下边说说饿汉式单例类:

<span style="font-size:18px;">public sealed  class  SingletonE  //注意这里的sealed修饰符,他的作用是防止继承此类     {         private static readonly SingletonE instance = new SingletonE();         private SingletonE() { }           public static SingletonE GetInstance()         {             return instance;         }     } </span>

饿汉与懒汉的区别:


饿汉:自己被加载时就将自己实例化,无需考虑多线程问题,加载速度快。但占用的资源较多

懒汉:第一次引用时,将自己实例化。因为引用时才会实例化,所以有一定的延时,加载速度慢,需要考虑多线程。


总结

这部分知识需要和别的模式对比进行记忆,总结完别的创建型模式,会写一篇他们之间差异的博客,都写到一篇里,感觉有点多,而且我这个小菜鸟也得自己消化消化,才能看的出来哪些是需要总结的点,继续加油


0 0