zoukankan      html  css  js  c++  java
  • 步步为营 .NET 设计模式学习笔记 四、Singleton(单例模式)

    概述
    Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点。这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程序在调用某一个类时,它是不会考虑这个类是否只能有一个实例等问题的,所以,这应该是类设计者的责任,而不是类使用者的责任。 
    从另一个角度来说,Singleton模式其实也是一种职责型模式。因为我们创建了一个对象,这个对象扮演了独一无二的角色,在这个单独的对象实例中,它集中了它所属类的所有权力,同时它也肩负了行使这种权力的职责!
    意图 
    保证一个类仅有一个实例,并提供一个访问它的全局访问点。
    模型图 
    逻辑模型图:
    物理模型图:<Design Pattern>Singleton示例
    比较:
    我们先对四种方式针对它们的优缺点进行一个比较:
      方法一:
      public sealed class Singleton
      {
      private static readonly Singleton instance = new Singleton();
      private Singleton(){}
      public static Singleton Instance
      {
      get
      {
      return instance;
      }
      }
      }
      优点:简单明了
      缺点:耗费资源
      方法二:
      public sealed class ClassicSingleton
      {
      private static ClassicSingleton instance;
      private static object syncRoot = new Object();
      private ClassicSingleton() { }
      public static ClassicSingleton Instance
      {
      get
      {
      if (instance == null)
      {
      lock (syncRoot)
      {
      if (instance == null)
      {
      //...custom code
      instance = new ClassicSingleton();
      }
      }
      }
      return instance;
      }
      }
      }
      优点:节省资源
      缺点:代码冗长
      方法三:
      public sealed class Singleton
      {
      static Singleton(){Instance = new Singleton();}
      private Singleton(){}
      public static Singleton Instance{get; private set;}
      }
      优点:既节省资源,又简单明了
      缺点:线程不安全
      方法四:
      public class Singleton
      {
      private static Singleton instance;
      // Added a static mutex for synchronising use of instance.
      private static System.Threading.Mutex mutex;
      private Singleton() { }
      static Singleton()
      {
      instance = new Singleton();
      mutex = new System.Threading.Mutex();
      }
      public static Singleton Acquire()
      {
      mutex.WaitOne();
      return instance;
      }
      // Each call to Acquire() requires a call to Release()
      public static void Release()
      {
      mutex.ReleaseMutex();
      }
      }
      优点:既节省资源,又简单明了,线程也安全了(一箭三雕)
      缺点:轻微冗长
    以下是我们的示例:
    在玩网游时,计算玩家在线人数,因为游对有很多大区,这时我们要用到单例模式.
    首先新建Example.cs:
    public sealed class Example
        {
            /// <summary>
            /// 定义一个静态的Example
            /// </summary>
            private static  Example SingleExample=new Example ();
            private int SumCount = 0;
            //私有构造函数
            private Example()
            
            /////线程延迟2000毫秒 
            Thread.Sleep(2000); 
      
            }
      
            //析构函数,避免最终都没有执行Dispose
             ~Example()
            {
                this.Dispose();
            }
            private void Dispose()
            {
                SingleExample = null;
            }
            /// <summary>
            /// 获取Example类型
            /// </summary>
            /// <returns></returns>
            public static Example GetExample()
            {
                if (SingleExample == null)
                    SingleExample = new Example();
                return SingleExample;
            }
            /// <summary>
            /// 记数加1
            /// </summary>
            public void AddCount()
            {
                SumCount++;
            }
            /// <summary>
            /// 返回记数
            /// </summary>
            /// <returns></returns>
            public int GetCount()
            {
                return SumCount;
            }
           
        }
    然后新建CountUserComeIn.cs:
     
    public  class CountUserComeIn
        {
            /// <summary>
            /// 用于返回信息
            /// </summary>
            public  StringBuilder strBuilder = new StringBuilder();
            public CountUserComeIn()
            
              
            }
            /// <summary>
            /// 调用Example
            /// </summary>
            public void GetUserComeIn()
            {
                 
                Example example = Example.GetExample();
                for (int i = 1; i <= 5; i++)
                {
                    example.AddCount();
                    strBuilder.AppendLine("现在的大区是:" + Thread.CurrentThread.Name);
                    strBuilder.AppendLine("现在共有" + example.GetCount() + "个玩家进入系统.");
                }
            }
            /// <summary>
            /// 新建三个实例
            /// </summary>
            public void Start()
            {
      
                Thread thread = Thread.CurrentThread;
                thread.Name = "华北区";
                Thread threadone = new Thread(new ThreadStart(GetUserComeIn));
                threadone.Name = "华东区";
                Thread threadtwo = new Thread(new ThreadStart(GetUserComeIn));
                threadtwo.Name = "华南区";
                Thread threadthree = new Thread(new ThreadStart(GetUserComeIn));
                threadthree.Name = "华中区";
                threadone.Start();
                threadtwo.Start();
                threadthree.Start();
       
                GetUserComeIn();
            }
        }
    然后调用:
    public partial class Run : Form
        {
            public Run()
            {
                InitializeComponent();
            }
      
            private void btnRun_Click(object sender, EventArgs e)
            {
                //ISaaSProcess process = new EmailEngine();
                //process.StartProcess();
                //process.StopProcess();
                //foreach (string result in process.GetResult())
                //{
                //    rtbResult.AppendText(result + "\n");
                //}
      
                //BuyComputer myBuy = new BuyComputer(new lenovo());
                // rtbResult.AppendText(myBuy.ShowComputerConfigure());
                //myBuy = new BuyComputer(new HP());
                // rtbResult.AppendText(myBuy.ShowComputerConfigure());
                CountUserComeIn CountUser = new CountUserComeIn();
                CountUser.Start();
                rtbResult.AppendText(CountUser.strBuilder.ToString());
      
            }
        }
    最近显示的结果:
    要注意以下三点:
    实现要点
            1、 Singleton模式是限制而不是改进类的创建。
            2、Singleton类中的实例构造器可以设置为Protected以允许子类派生。
            3、Singleton模式一般不要支持Icloneable接口,因为这可能导致多个对象实例,与Singleton模式的初衷违背。
            4、Singleton模式一般不要支持序列化,这也有可能导致多个对象实例,这也与Singleton模式的初衷违背。
            5、Singleton只考虑了对象创建的管理,没有考虑到销毁的管理,就支持垃圾回收的平台和对象的开销来讲,我们一般没必要对其销毁进行特殊的管理。
            6、 理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的构造器的任意调用”。 
            7、可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的。
    优点
             实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例
             灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程
    缺点
            开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题,上面的五种实现方式中已经说过了。
              可能的开发混淆:使用 singleton 对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用 new 关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
             对象的生存期:Singleton 不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于 .NET Framework 的语言),只有 Singleton 类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致 Singleton 类中出现悬浮引用。
        欢迎拍砖!
    http://u.huoban001.com/space.php
  • 相关阅读:
    python模块
    python函数进阶
    python函数
    六.python的深浅拷贝
    五.集合及其推导式
    IOS微信显示NAN,中国标准时间日期转换
    Caused by: org.apache.ibatis.binding.BindingException: Parameter 'XXX' not found. Available parameters are [beginTime, endTime, param3, param1, vesselName, param2] 找不到参数的解决方式
    java的nullpointerexception空指针异常,关于使用了timer定时导致service调用问题
    java设置开始时间,定时执行任务
    java多层嵌套集合的json,如何获取多层集合中所需要的value
  • 原文地址:https://www.cnblogs.com/zpq521/p/2067509.html
Copyright © 2011-2022 走看看