qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          跟屌絲大哥學設計模式-單例模式

          概念:
            java中單例模式是一種常見的設計模式,單例模式分三種:懶漢式單例、餓漢式單例、登記式單例三種。
          哈哈 我們可以這樣分 屌絲單例模式:懶漢式屌絲單例,餓漢式屌絲單例,登記式屌絲單例。

            單例模式有一下特點:
            1、單例類只能有一個實例。
            2、單例類必須自己自己創建自己的唯一實例。
            3、單例類必須給所有其他對象提供這一實例。

          單例模式確保某個類只有一個實例,而且自行實例化并向整個系統提供這個實例。在計算機系統中,線程池、緩存、日志對象、對話框、打印機、顯卡的驅動程序對象常被設計成單例。這些應用都或多或少具有資源管理器的功能。每臺計算機可以有若干個打印機,但只能有一個Printer Spooler,以避免兩個打印作業同時輸出到打印機中。每臺計算機可以有若干通信端口,系統應當集中管理這些通信端口,以避免一個通信端口同時被兩個請求同時調用。總之,選擇單例模式就是為了避免不一致狀態,避免政出多頭。

          首先看一個經典的單例實現。

          public class Singleton {

              private static Singleton uniqueInstance = null;

           

              private Singleton() {

                 // Exists only to defeat instantiation.

              }

           

              public static Singleton getInstance() {

                 if (uniqueInstance == null) {

                     uniqueInstance = new Singleton();

                 }

                 return uniqueInstance;

              }

              // Other methods...

          }

          Singleton通過將構造方法限定為private避免了類在外部被實例化,在同一個虛擬機范圍內,Singleton的唯一實例只能通過getInstance()方法訪問。(事實上,通過Java反射機制是能夠實例化構造方法為private的類的,那基本上會使所有的Java單例實現失效。此問題在此處不做討論,姑且掩耳盜鈴地認為反射機制不存在。)

          但是以上實現沒有考慮線程安全問題。所謂線程安全是指:如果你的代碼所在的進程中有多個線程在同時運行,而這些線程可能會同時運行這段代碼。如果每次運行結果和單線程運行的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的。或者說:一個類或者程序所提供的接口對于線程來說是原子操作或者多個線程之間的切換不會導致該接口的執行結果存在二義性,也就是說我們不用考慮同步的問題。顯然以上實現并不滿足線程安全的要求,在并發環境下很可能出現多個Singleton實例。

          public class TestDiaoSiStream {
               private String DiaoSiname;
               public String getDiaoSiname() {
                   return DiaoSiname;
               }
               public void setDiaoSiname(String DiaoSiname) {
                   this.DiaoSiname = DiaoSiname;
               } 
               //該類只能有一個實例
               private TestDiaoSiStream(){}    //私有無參構造方法
               //該類必須自行創建
               //有2種方式
               /*private static final TestDiaoSiStream ds=new TestDiaoSiStream();*/
               private static TestDiaoSiStream ds1=null;
               //這個類必須自動向整個系統提供這個實例對象
               public static TestDiaoSiStream getTestDiaoSiTest(){
                   if(ds1==null){
                       ds1=new TestDiaoSiStream();
                   }
                   return ds1;
               }
               public void getInfo(){
                   System.out.println("output message "+DiaoSiname);
               }
           }

          public class TestMain {
               public static void main(String [] args){
                   TestDiaoSiStream  ds=TestDiaoSiStream.getTestDiaoSiTest();
                   ds.setDiaoSiname("奶娃");
                   System.out.println(ds.getDiaoSiname());
                   TestDiaoSiStream ds1=TestDiaoSiStream.getTestDiaoSiTest();
                   ds1.setDiaoSiname("奶娃");
                   System.out.println(ds1.getDiaoSiname());
                   ds.getInfo();
                   ds1.getInfo();
                   if(ds==ds1){
                       System.out.println("創建的是同一個屌絲實例");
                   }else if(ds!=ds1){
                       System.out.println("創建的不是同一個屌絲實例");
                   }else{
                       System.out.println("application error");
                   }
               }
           }

          運行結果:
            奶娃
            奶娃
            output message 奶娃
            output message 奶娃
            創建的是同一個屌絲
          實例

          結論:由結果可以得知單例模式為一個面向對象的應用程序提供了對象惟一的訪問點,不管它實現何種功能,整個應用程序都會同享一個實例對象

          1.餓漢式單例類

          //餓漢式單例類.在類初始化時,已經自行實例化 
           public class Singleton1 {
               //私有的默認構造子
               private Singleton1() {}
               //已經自行實例化 
               private static final Singleton1 single = new Singleton1();
               //靜態工廠方法 
               public static Singleton1 getInstance() {
                   return single;
               }
           }

          2.懶漢式單例類
          //懶漢式單例類.在第一次調用的時候實例化 
           public class Singleton2 {
               //私有的默認構造子
               private Singleton2() {}
               //注意,這里沒有final    
               private static Singleton2 single=null;
               //靜態工廠方法 
               public synchronized  static Singleton2 getInstance() {
                    if (single == null) {  
                        single = new Singleton2();
                    }  
                   return single;
               }
           }
          3.登記式單例類

          import java.util.HashMap;
           import java.util.Map;
           //登記式單例類.
           //類似Spring里面的方法,將類名注冊,下次從里面直接獲取。
           public class Singleton3 {
               private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
               static{
                   Singleton3 single = new Singleton3();
                   map.put(single.getClass().getName(), single);
               }
               //保護的默認構造子
               protected Singleton3(){}
               //靜態工廠方法,返還此類惟一的實例
               public static Singleton3 getInstance(String name) {
                   if(name == null) {
                       name = Singleton3.class.getName();
                       System.out.println("name == null"+"--->name="+name);
                   }
                   if(map.get(name) == null) {
                       try {
                           map.put(name, (Singleton3) Class.forName(name).newInstance());
                       } catch (InstantiationException e) {
                           e.printStackTrace();
                       } catch (IllegalAccessException e) {
                           e.printStackTrace();
                       } catch (ClassNotFoundException e) {
                           e.printStackTrace();
                       }
                   }
                   return map.get(name);
               }
               //一個示意性的商業方法
               public String about() {    
                   return "Hello, I am RegSingleton.";    
               }    
               public static void main(String[] args) {
                   Singleton3 single3 = Singleton3.getInstance(null);
                   System.out.println(single3.about());
               }
           }

          posted on 2012-12-07 14:55 順其自然EVO 閱讀(463) 評論(0)  編輯  收藏 所屬分類: 設計模式學習

          <2012年12月>
          2526272829301
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 屏南县| 明水县| 桃园县| 句容市| 同江市| 长沙县| 临夏县| 阜阳市| 南召县| 嘉祥县| 随州市| 鹤峰县| 济阳县| 阜阳市| 阿拉善左旗| 太仓市| 东海县| 家居| 新兴县| 梧州市| 炎陵县| 怀柔区| 海丰县| 宁城县| 定安县| 综艺| 文昌市| 竹北市| 广水市| 阿勒泰市| 普格县| 平定县| 五常市| 灵台县| 庄河市| 四平市| 突泉县| 青阳县| 虹口区| 怀来县| 乌兰浩特市|