zoukankan      html  css  js  c++  java
  • NET设计模式-单例模式(Singleton Pattern)

    1. 概述

    Singleton Pattren 要求一个类有且仅有一个实例,并且提供一个全局变量。这个创建的对象是独一无二的,在这个单独对象实例中,集中所创建类的所有属性和方法。
    在创建一个单例,何时需要,这是程序设计的关键。从定义上可知这个类供全局调用,产品(程序)都可调用,所有是个全局静态变量,一般是不允许有派生类的。比如,火车的票数及票种,必须全局变量,这个往往是为了防止多线程调用时,导致问题溢出。

    2. 模型图及思路

    实例图

    思路图

    3. 代码实现

    //单例模式类不能派生
    public sealed class Singleton
    {
        //静态对象,才能在静态函数中访问
        private static Singleton uniqueInstance;
    
        //线程安全控制实例
        static object synobj = new object();
        public static Singleton GetInstace()
        {
             //不加线程控制时,当两个线程同时运行GetInstance方法时,此时两个线程判断(uniqueInstance ==null)这个条件时都返回真,此时两个线程就都会创建Singleton的实例
                // 当第一个线程运行到这里时,此时会对locker对象 "加锁",
                // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
                // lock语句运行完之后(即线程运行完之后)会对该对象"解锁"
            lock(synobj)
            {
                // 如果类的实例不存在则创建,否则直接返回
                 //为创建实例时,进行创建
               if (uniqueInstance == null)
               {
                    uniqueInstance = new Singleton();
               }
          }
            return uniqueInstance;
        }
    
        //私有构造函数,只允许在此类中创建对象
        private Singleton()
        {
        }
    
    }
    View Code

    以上的设计确实解决多线程的问题,但是上面的代码对于每个线程辅助对象locker枷锁后,在判断实例时候存在,对于这个操作完全没必要。可以当地一个线程创建实例后,后面的线程只需要直接判断是否为null。就如一下的代码。

    //单例模式类不能派生
    public sealed class Singleton
    {
        //静态对象,才能在静态函数中访问
        private static Singleton uniqueInstance;
    
        //线程安全控制实例
        static object synobj = new object();
        public static Singleton GetInstace()
        {
             //不加线程控制时,当两个线程同时运行GetInstance方法时,此时两个线程判断(uniqueInstance ==null)这个条件时都返回真,此时两个线程就都会创建Singleton的实例
                // 当第一个线程运行到这里时,此时会对locker对象 "加锁",
                // 当第二个线程运行该方法时,首先检测到locker对象为"加锁"状态,该线程就会挂起等待第一个线程解锁
                // lock语句运行完之后(即线程运行完之后)会对该对象"解锁" 
                //只需要家这句判断就可以了
          if(uniqueInstance == null)
           {
            lock(synobj)
            {
                // 如果类的实例不存在则创建,否则直接返回
                 //为创建实例时,进行创建
               if (uniqueInstance == null)
               {
                    uniqueInstance = new Singleton();
               }
          }
         }
            return uniqueInstance;
        }
    
        //私有构造函数,只允许在此类中创建对象
        private Singleton()
        {
        }
    
    }
    View Code
    public sealed class Singleton
     {
        static readonly Singleton instance=new Singleton();
     
         static Singleton()
         {
         }
     
         Singleton()
        {
        }
    
        public static Singleton Instance
        {
            get
            {
                return instance;
            }
        }
     }
    View Code
    
    

    看到上面这段富有戏剧性的代码,我们可能会产生怀疑,这还是Singleton模式吗?在此实现中,将在第一次引用类的任何成员时创建实例。公共语言运行库负责处理变量初始化。该类标记为 sealed 以阻止发生派生,而派生可能会增加实例。此外,变量标记为 readonly,这意味着只能在静态初始化期间(此处显示的示例)或在类构造函数中分配变量。

    该实现与前面的示例类似,不同之处在于它依赖公共语言运行库来初始化变量。它仍然可以用来解决 Singleton 模式试图解决的两个基本问题:全局访问和实例化控制。公共静态属性为访问实例提供了一个全局访问点。此外,由于构造函数是私有的,因此不能在类本身以外实例化 Singleton 类;因此,变量引用的是可以在系统中存在的唯一的实例。
    由于 Singleton 实例被私有静态成员变量引用,因此在类首次被对 Instance 属性的调用所引用之前,不会发生实例化。

    4.要点知识

    1. Singleton模式是限制而不是创建。
    2. Singleton类中实例可以设置为Protected供子类派生
    3. Singleton考虑了对象创建的管理,没有进行销毁,就支持垃圾回收的平台,就不用对销毁进行管理。
    4. 优点:阻止其他对象实例化自己的副本,保证所有对象访问的唯一实例。
    5. 缺点:使用Singleton模式时,开发人员不能有new,进行实例化。

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    js取当前时间的秒级时间戳
    微信自动聊天脚本
    小程序 缓存过期问题
    去掉表格默认样式
    css3 画心
    数据导入(二):MapReduce
    数据导入(一):Hive On HBase
    HBase参数优化
    Hadoop运维手记
    HBase优化相关
  • 原文地址:https://www.cnblogs.com/polly333/p/4705679.html
Copyright © 2011-2022 走看看