數(shù)據(jù)加載中……
          設(shè)計(jì)模式之單例模式詳解

          如果說(shuō)道設(shè)計(jì)模式,我想大家想到最多的應(yīng)該就是單例模式和工廠模式,上一篇文章中詳細(xì)介紹了工廠模式以及簡(jiǎn)單工廠模式和抽象工廠模式。相對(duì)工廠模式,單例模式要簡(jiǎn)單一點(diǎn),但是單例模式也同樣有很多值得思考的問(wèn)題,下面就來(lái)看一下這些問(wèn)題以及解決的辦法。

          1、靜態(tài)初始化實(shí)例對(duì)象(網(wǎng)上也有人叫饑餓實(shí)例化)

          public class EagerSingleton {

              private static final EagerSingleton instance = new EagerSingleton();

              private EagerSingleton() {

              }

              public static EagerSingleton getInstance() {

                  return EagerSingleton.instance;

              }

          }

          2、當(dāng)?shù)谝淮涡枰臅r(shí)候創(chuàng)建實(shí)例化對(duì)象(懶漢實(shí)例化)

          public class LazySingleton {

              private static LazySingleton instance = null;

              private LazySingleton() {

              }

              public synchronized static LazySingleton getInstance() {    

                  if(instance == null) {

                      instance = new LazySingleton();

                  }

                  return instance;

              }

          }

          這里一定要注意加synchronized,否則就會(huì)引進(jìn)多線程下的不安全的情況了。

          但是,考慮到synchronized加在方法上,鎖的粒度太多,會(huì)對(duì)性能產(chǎn)生影響。所以引入下面的dcl算法進(jìn)行改進(jìn)。

          3、采用dcl算法改進(jìn)2(關(guān)于dcl請(qǐng)看這個(gè)http://en.wikipedia.org/wiki/Double-checked_locking,后面找時(shí)間詳細(xì)聊聊這個(gè)東西,貌似是jee中一個(gè)很常用的東西)

          public class DclLazySingleton {

              private static DclLazySingleton instance = null;

              private DclLazySingleton() {

              }

              public static DclLazySingleton getInstance() {

                  if(instance == null) {

                      synchronized(DclLazySingleton.class) {

                          if(instance == null) {

                              instance = new DclLazySingleton();

                          }

                      }

                  }

                  return instance;

              }

          }

          ps:按照wiki的說(shuō)法,這種算法是有問(wèn)題,這個(gè)后面在討論,不過(guò)貌似異常出現(xiàn)的概率很小,而且很多成功的開(kāi)源項(xiàng)目都用到了它,所以,不用擔(dān)心!

          4、看到這里,是不是大家覺(jué)得單例模式就該解決了呢?可是有沒(méi)有發(fā)現(xiàn)一個(gè)問(wèn)題呢?上面的單例類都不能做父類,因?yàn)闃?gòu)造方法是私有的,ps,子類的構(gòu)造方法默認(rèn)會(huì)去調(diào)用父類的構(gòu)造方法,如果是私有的,這個(gè)果斷沒(méi)法繼承啊。

          所以就引進(jìn)了下面的注冊(cè)式的單例實(shí)現(xiàn)方式??淳W(wǎng)上很多人都說(shuō)spring中使用了這種方式,所以開(kāi)始了解這種方式,其實(shí)經(jīng)典的GoF的書(shū)中就有對(duì)這個(gè)的介紹。

          public class RegisterSingleton {

              private static Map<String, RegisterSingleton> instanceMap = new HashMap<String, RegisterSingleton>();

              static {

                  RegisterSingleton instanceThis = new RegisterSingleton();

                  instanceMap.put(RegisterSingleton.class.getName(), instanceThis);

              }

              protected RegisterSingleton() {

              }

              public static RegisterSingleton getInstance(String name) {

                  if(name == null) {

                      name = RegisterSingleton.class.getName();

                  }

                  if(instanceMap.get(name) == null) {

                      try {

                          instanceMap.put(name, (RegisterSingleton)Class.forName(name).newInstance());

                      } catch (InstantiationException e) {

                          e.printStackTrace();

                      } catch (IllegalAccessException e) {

                          e.printStackTrace();

                      } catch (ClassNotFoundException e) {

                          e.printStackTrace();

                      }

                  }

                  return instanceMap.get(name);

              }

              public static RegisterSingleton getInstance() {

                  return getInstance(RegisterSingleton.class.getName());

              }

          }

          使用重載來(lái)便捷的調(diào)用getInstance()方法。

          子類如果繼承去調(diào)用getInstance方法呢?請(qǐng)看如下代碼:

          public class RegisterSingletonChild extends RegisterSingleton {

              protected RegisterSingletonChild() {}

              public static RegisterSingletonChild getInstance() {

                  return (RegisterSingletonChild)RegisterSingleton.getInstance(RegisterSingletonChild.class.getName());

              }

          }

          當(dāng)然,如果子類確定沒(méi)有子類的話,則可以考慮用private去替代protected.

          5、總結(jié)

          以上4種方式基本包含了單例模式使用的四種方法,考慮了多線程下單例模式的線程安全性和有繼承情況下的注冊(cè)式單例實(shí)現(xiàn)。
          老規(guī)矩上pdf,呵呵。/Files/zhenxuanpan/設(shè)計(jì)模式之單例模式的詳解.pdf

          posted on 2011-08-25 00:03 潘潘.eagle 閱讀(293) 評(píng)論(0)  編輯  收藏 所屬分類: Design Pattern


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 林西县| 乐清市| 文昌市| 韶关市| 阿坝| 吴旗县| 都兰县| 广东省| 新沂市| 新龙县| 河东区| 长沙县| 四川省| 伊宁县| 蒙城县| 洛阳市| 天长市| 察隅县| 广安市| 东乡县| 乐昌市| 赣榆县| 宁蒗| 凤翔县| 古丈县| 台安县| 福建省| 三江| 洛川县| 都江堰市| 九龙坡区| 靖江市| 股票| 天门市| 大兴区| 陆川县| 通化县| 莱芜市| 岳普湖县| 北宁市| 乌兰浩特市|