zoukankan      html  css  js  c++  java
  • 设计模式 单件模式(Signleton Pattern)

        尽管在某种程度上,单件模式是限制而不是改进类的创建,但它仍和其他创建模式分在一组。单件模式可以保证一类有且只有一个实例,并提供一个访问它的全局访问点,在程序设计过程中,有很多情况需要确保一个类只能有一个实例。例如系统中能有一个窗口管理器,一个数据库引擎的访问点。PC机中可能有几个串口,但只能有一个COM1实例。
    使用静态方法创建单件
        让一个类只有一个实例,最容易的方法就是在类中嵌入一个静态变量,并在第一个类实例中设置改变量,而且每次进入构造函数都要检查。不管类有多少实例,静态变量只能有一个实例。为了防止类被多次实例化,我们把构造函数声明为私有的,这样只能在类的静态方法里创建一个实例。下面创建一个
    getSpooler方法,返回Spooler的一个实例,如果类已经被实例化,返回值为null。

     1 using System;
    2
    3 namespace GlobalSpooler
    4 {
    5 /// <summary>
    6 /// Summary description for Spooler.
    7 /// </summary>
    8 public class Spooler {
    9 private static bool instance_flag= false;
    10 private Spooler() {
    11 }
    12 public static Spooler getSpooler() {
    13 if (! instance_flag)
    14 return new Spooler ();
    15 else
    16 return null;
    17 }
    18
    19 }
    20 }

      这中方法的主要优点是,如果单件存在了,不需要考虑异常处理,因为只不过getSpooler方法返回一个空值而已。

    1 Spooler sp1 = Spooler.getSpooler();
    2 if (sp1 != null)
    3 Console.WriteLine ("Got 1 spooler");
    4 Spooler sp2 = Spooler.getSpooler ();
    5 if (sp2 == null)
    6 Console.WriteLine ("Can\'t get spooler");

    如果视图直接创建Spoolet类的实例,编译会失败,因为构造函数被声明为私有的。

    1 //fails at compile time
    2 Spooler sp3 = new Spooler ();

    最后,如果需要修改程序,允许该类有两个或者三个实例,则修改spooler类可以很容易实现这一点。
        
    异常与实例
        前面方法有个缺点,需要程序员检查方法的返回值,以确保它不为空。让程序员始终记得去检查错误的设想是导致失败的开始,应该尽量避免。我们换种方法,创建一个这样的类,如果视图多次实例化该类,它会抛出一个异常,这时才需要程序员采取行动,因而这时一个安全的方法,这里先为这个例子创建异常类。

     1 using System;
    2
    3 namespace singleSpooler
    4 {
    5 /// <summary>
    6 /// Summary description for SingletonException.
    7 /// </summary>
    8 public class SingletonException:Exception {
    9 //new exception type for singleton classes
    10 public SingletonException(string s):base(s) {
    11 }
    12 }
    13 }

    抛出异常
    接下来给出PrintSpooler类的框架。这里略去打印方法,只集中在单件模式

     1 using System;
    2
    3 namespace singleSpooler
    4 {
    5 /// <summary>
    6 /// Prototype of Spooler Singleton
    7 /// such that only one instane can ever exist.
    8 /// </summary>
    9 public class Spooler {
    10 static bool instance_flag = false; //true if one instance
    11 public Spooler() {
    12 if (instance_flag)
    13 throw new SingletonException("Only one printer allowed");
    14 else
    15 instance_flag=true; //set flag for one instance
    16 Console.WriteLine ("printer opened");
    17 }
    18 }
    19 }

    创建一个实例
    我们已经在PrintSpooler类里创建了一个简单的单件模式,接下来就去了解如果使用它

     1 using System;
    2
    3 namespace singleSpooler
    4 {
    5 /// <summary>
    6 /// Summary description for Class1.
    7 /// </summary>
    8 public class singleSpooler {
    9 static void Main(string[] args) {
    10 Spooler pr1, pr2;
    11 //open one printer--this should always work
    12 Console.WriteLine ("Opening one spooler");
    13 try {
    14 pr1 = new Spooler();
    15 }
    16 catch (SingletonException e) {
    17 Console.WriteLine (e.Message);
    18 }
    19 //try to open another printer --should fail
    20 Console.WriteLine ("Opening two spoolers");
    21 try{
    22 pr2 = new Spooler();
    23 }
    24 catch (SingletonException e) {
    25 Console.WriteLine (e.Message);
    26 }
    27 }
    28 }
    29 }

    执行结果

    提供一个单件的全局访问点
        由于使用电击模式提供一个类的全局访问点,即使C#中没有全局变量,设计程序是也必须为整个程序提供引用单件方法。一种解决方案是在程序的开头创建单件模式,并将其作为参数传递到使用它的类中。这种方法的 缺点是,在某次程序运行中,可能不需要所有的单件,这样会影响程序的性能。

    1 prl = iSpooler.Instance();
    2 Customers cust = new Customers(prl);

        另一种更灵活的解决方案是,在程序中创建一个所有单件类的注册表,并使用注册表始终是可用的,每一次实例化一个组件,都将其记录在注册表中。程序的任何部分都是用标示符串访问任何一个单件实例,并能取回相应的实例变量。注册表的缺点是减少了类型检查,因为注册表中的单件可能把所有的单件都保存成对象型,例如,Hashtable中的对象类型,另外,注册表本身可能也是一个单件,必须使用构造函数或者其他set函数吧它传递给程序的所有部分。提供一个全局访问点的最常用的方式就是使用类的静态方法。类名始终是可用的,静态方法只能由类调用不能由类的实例调用,所以不管程序中有多少方法调用该方法,永远只能有一个这样的实例。


    单例模式的其他效果
    1.子类化一个单件很难,因为只有在基类单件没有实例化时,才能实现这一点。
    2.可能很容易修改一个单件,使它有少数几个实例,这样做事允许的而且有意义的。

       


    人生如棋、我愿为卒、行动虽缓、从未退过

  • 相关阅读:
    c++再探string之eager-copy、COW和SSO方案
    C++之运算符重载
    numpy之随机数模块---random模块
    numpy之特征值、奇异值分解及其在图片处理中的应用
    numpy之傅里叶定理
    numpy之矩阵
    numpy之函数
    numpy之数据平滑处理
    numpy之多项式
    numpy之相关矩阵求解
  • 原文地址:https://www.cnblogs.com/sunjinpeng/p/2419729.html
Copyright © 2011-2022 走看看