Design Pattern: Registry of Singleton 模式

  学习是分享和合作式的!

转载请注明出处:http://blog.csdn.net/wdzxl198/article/details/9248821; 

文章摘自: http://www.riabook.cn/doc/designpattern/; 

考虑使用 Singleton 模式 时拥有子类别的问题,在Singleton模式中的getInstance()通常是一个静态方法,不能在子类别中重新定义它,关于子类别实例的产生交由getInstance()来进行是最好的选择,例如:

   1: public class Singleton {
   2:      private static Singleton instance = null;
   3:      private Singleton() 
   4:     {
   5:          // ....
   6:  
   7:     }
   8:      public static Singleton getInstance() 
   9:     {
  10:         if (instance == null) 
  11:         {
  12:      // 
  13:             getEnv表示系统环境变数
  14:              
  15:             String style = getEnv("style");
  16:              
  17:             if (style.equals("child1")) 
  18:                 instance = new ChildSingleton1(); 
  19:             else if(style.equals("child2r"))
  20:                 instance = new ChildSingleton2();
  21:              else
  22:                 instance = new Singleton();
  23:            }
  24:            return _instance;
  25:      }
  26:      // ....
  27: }

上面这个程式片段改写自 Gof 书中关于Singleton的例子,并用Java实现;在书中指出,这个例子的缺点是每增加一个子类别,getInstance()就必须重新修改,这个问题在Java中可以使用Reflection机制来解决:

   1: public class Singleton {
   2:     private static Singleton instance = null;
   3:     private Singleton() {
   4:         // ....
   5:     }
   6:     public static Singleton getInstance() {
   7:         if (instance == null) {
   8:             // getEnv表示环境变数
   9:             String style = getEnv("style");
  10:             try {
  11:                 instance = (Singleton)
  12:                           Class.forName(style).newInstance();
  13:             }
  14:             catch(Exception e) {
  15:                 System.out.println(
  16:                    "Sorry! No such class defined!");
  17:             }
  18:         }
  19:         return instance;
  20:     }
  21:     // ....
  22: }

上面的方式使用了Java的Reflection机制,并透过环境变数设定要产生的子类Singleton,如果不使用Reflection的话,Gof 书中提出的改进方法是使用Registry of Singleton方法:

   1: import java.util.*;
   2: public class Singleton {
   3:     // 注册表,用于注册子类别物件
   4:     private static Map registry = new HashMap();
   5:     private static Singleton instance;
   6:     public static void register(
   7:                  String name, Singleton singleton) {
   8:         registry.put(name, singleton);
   9:     }
  10:     public static Singleton getInstance() {
  11:         if (instance == null) {
  12:             // getEnv表示取得环境变数
  13:             String style = getEnv("style");
  14:             instance = lookup(style);
  15:         }
  16:         return instance;
  17:     }
  18:     protected static Singleton lookup(String name) {
  19:         return (Singleton) registry.get(name);
  20:     }
  21: }

在Gof书中使用List来实现注册表,而在这边使用HasMap类别来实现,它是由Java SE所提供的;在父类别中提供一个register() 以注册Singleton的子类别所产生之实例,而注册的时机可以放在子类别的建构方法中加以实现,例如:

   1: public class ChildSingleton1 extends Singleton {
   2:     public ChildSingleton1() {
   3:         // ....
   4:         // 注册子类别物件
   5:         register(getClass().getName(), this); 
   6:     }
   7: }

若要利用Singleton,则先使用这个子类别产生物件,这会向父类别注册物件,之后透过Singleton父类别来取得物件:

   1: // 必须先启始这段注册程序
   2: // 产生并注册ChildSingleton1物件
   3: new ChildSingleton1();
   4: // 产生并注册ChildSingleton2物件
   5: new ChildSingleton2();
   6:  
   7: // 注册完成,可以使用父类别来取得子类的Singleton
   8: // 至于取回何哪一个,视您的环境变数设置决定
   9: Singleton childSingleton = Singleton.getInstance();
  10:  
这种方式的缺点是您必须在程式中启始一段程序,先向父类别注册子类的Singleton,之后才能透过父类别来取得指定的子类别Singleton实例, 好处是可以适用于没有Reflection机制的语言,如果您想要改变Singleton父类传回的子类Singleton,可以在上面的 Singleton类别中加入一个reset()方法,将instance设定为null,然后重新设定环境变数,之后再利用 Singleton父类的getInstance()方法重新取得注册表中的其它子类。
事实上Registry of Singleton的真正优点正在于此,您可以使用父类别来统一管理多个继承的子类别之Singleton实例,您可以在需要的时候再向父类别注册子类 Singleton,必要时随时调整传回的子类别Singleton。

Edit by Atlas

Time 2013/7/5 09:31

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值