乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      創(chuàng)建型設(shè)計模式--單例模式

       路人甲Java 2020-06-28

      一、單例模式

      1、什么是單例模式

        采取一定的方法,使程序中的某個類只存在一個實例對象,且該類對外提供一個獲取該對象的方法(一般為靜態(tài)方法)。

      2、單例模式分類

      (1)餓漢式(2種寫法,線程安全)
        靜態(tài)變量
        靜態(tài)代碼塊

      (2)懶漢式(3種寫法)
        線程不安全
        線程安全,同步方法
        線程安全,同步代碼塊(不推薦使用)

      (3)雙重檢查(推薦使用)
      (4)靜態(tài)內(nèi)部類(推薦使用)
      (5)枚舉(推薦使用)

      3、餓漢式單例模式(靜態(tài)常量版)

      (1)步驟:
        step1:構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
        step2:在類的內(nèi)部創(chuàng)建實例對象。
        step3:向外暴露一個靜態(tài)的公共方法用于獲取實例對象。
      (2)代碼實現(xiàn):

      package singleton.pattern.demo1;
      
      /**
       * 演示 餓漢式單例模式,靜態(tài)變量版
       *
       */
      public class Demo {
          public static void main(String[] args) {
              Singleton singleton1 = Singleton.getSingleTon();
              Singleton singleton2 = Singleton.getSingleTon();
              System.out.println(singleton1 == singleton2); // 由于獲取的為同一個對象,所以輸出為true
          }
      }
      
      /**
       * 餓漢式單例模式,靜態(tài)變量版
       */
      class Singleton {
          // 在類的內(nèi)部創(chuàng)建實例對象。使用靜態(tài)變量,只被加載一次。
          private static Singleton singleton = new Singleton();
      
          /**
           * 構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
           */
          private Singleton() {
          }
      
          /**
           * 向外暴露一個靜態(tài)的公共方法用于獲取實例對象。
           * 
           * @return 實例對象
           */
          public static Singleton getSingleTon() {
              return singleton;
          }
      }

      (3)優(yōu)缺點:
        優(yōu)點:寫法簡單,在類裝載時完成了實例化,避免線程同步問題。
        缺點:在類裝載前完成實例化,沒有實現(xiàn)懶加載(Lazy Loading),可能造成內(nèi)存的浪費(比如從不使用該類時會造成內(nèi)存的浪費)。

      (4)UML圖:

       

      4、餓漢式單例模式(靜態(tài)代碼塊)

      (1)步驟:
        step1:構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
        step2:在類的內(nèi)部聲明實例對象,并在靜態(tài)代碼塊中實例化對象。
        step3:向外暴露一個靜態(tài)的公共方法用于獲取實例對象。
      (2)代碼實現(xiàn):

      package singleton.pattern.demo2;
      
      /**
       * 演示 餓漢式單例模式,靜態(tài)代碼塊版
       *
       */
      public class Demo {
          public static void main(String[] args) {
              Singleton singleton1 = Singleton.getSingleTon();
              Singleton singleton2 = Singleton.getSingleTon();
              System.out.println(singleton1 == singleton2); // 由于獲取的為同一個對象,所以輸出為true
          }
      }
      
      /**
       * 餓漢式單例模式,靜態(tài)代碼塊版
       */
      class Singleton {
          // 在類的內(nèi)部聲明一個實例對象
          private static Singleton singleton;
      
          static {
              // 在代碼塊中實例化一個對象,同樣只加載一次
              singleton = new Singleton();
          }
      
          /**
           * 構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
           */
          private Singleton() {
          }
      
          /**
           * 向外暴露一個靜態(tài)的公共方法用于獲取實例對象。
           * 
           * @return 實例對象
           */
          public static Singleton getSingleTon() {
              return singleton;
          }
      }

      (3)優(yōu)缺點同上例 餓漢式單例模式(靜態(tài)常量版)

      5、懶漢式單例模式(線程不安全)

      (1)步驟:
        step1:構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
        step2:在類的內(nèi)部聲明實例對象。
        step3:向外暴露一個靜態(tài)的公共方法用于獲取實例對象,在調(diào)用該方法時,才去創(chuàng)建實例對象。
      (2)代碼實現(xiàn):

      package singleton.pattern.demo3;
      
      /**
       * 演示 懶漢式單例模式,線程不安全版
       *
       */
      public class Demo {
          public static void main(String[] args) {
              Singleton singleton1 = Singleton.getSingleTon();
              Singleton singleton2 = Singleton.getSingleTon();
              System.out.println(singleton1 == singleton2); // 由于獲取的為同一個對象,所以輸出為true
          }
      }
      
      /**
       * 懶漢式單例模式,線程不安全版
       */
      class Singleton {
          // 在類的內(nèi)部聲明一個實例對象
          private static Singleton singleton;
      
          /**
           * 構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
           */
          private Singleton() {
          }
      
          /**
           * 向外暴露一個靜態(tài)的公共方法用于獲取實例對象。 當(dāng)調(diào)用該方法時,才去檢查并創(chuàng)建一個實例對象。
           * 
           * @return 實例對象
           */
          public static Singleton getSingleTon() {
              if (singleton == null) {
                  singleton = new Singleton();
              }
              return singleton;
          }
      }

      (3)優(yōu)缺點:
        優(yōu)點:實現(xiàn)了懶加載。
        缺點:只能在單線程下使用,比如線程A與線程B并發(fā)執(zhí)行到 if (singleton == null), 此時便會產(chǎn)生多個實例對象。

      6、懶漢式單例模式(線程安全,同步方法)

      (1)步驟:
        step1:構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
        step2:在類的內(nèi)部聲明實例對象。
        step3:向外暴露一個靜態(tài)的公共方法(給靜態(tài)方法加個synchronized關(guān)鍵字,解決同步問題)用于獲取實例對象,在調(diào)用該方法時,才去創(chuàng)建實例對象。
      (2)代碼實現(xiàn):

      package singleton.pattern.demo4;
      
      /**
       * 演示 懶漢式單例模式,線程安全,同步方法版
       *
       */
      public class Demo {
          public static void main(String[] args) {
              Singleton singleton1 = Singleton.getSingleTon();
              Singleton singleton2 = Singleton.getSingleTon();
              System.out.println(singleton1 == singleton2); // 由于獲取的為同一個對象,所以輸出為true
          }
      }
      
      /**
       * 懶漢式單例模式,線程安全,同步方法版
       */
      class Singleton {
          // 在類的內(nèi)部聲明一個實例對象
          private static Singleton singleton;
      
          /**
           * 構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
           */
          private Singleton() {
          }
      
          /**
           * 向外暴露一個靜態(tài)的公共方法用于獲取實例對象,并給方法加個synchronized關(guān)鍵字,解決同步的問題。
           * 當(dāng)調(diào)用該方法時,才去檢查并創(chuàng)建一個實例對象。
           * 
           * @return 實例對象
           */
          public static synchronized Singleton getSingleTon() {
              if (singleton == null) {
                  singleton = new Singleton();
              }
              return singleton;
          }
      }

      (3)優(yōu)缺點:
        優(yōu)點:實現(xiàn)了懶加載,解決了線程不安全的問題。
        缺點:效率太低,每個線程想獲取實例對象時,均會觸發(fā)同步方法,此時會等待前一個線程調(diào)用結(jié)束后才能使用,使效率低。

       

      7、懶漢式單例模式(同步代碼塊方法,線程不一定安全)

      (1)步驟:
        step1:構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
        step2:在類的內(nèi)部聲明實例對象。
        step3:向外暴露一個靜態(tài)的公共方法(在靜態(tài)方法內(nèi)部定義一個代碼塊,解決同步問題)用于獲取實例對象,在調(diào)用該方法時,才去創(chuàng)建實例對象。
      (2)代碼實現(xiàn):

      package singleton.pattern.demo5;
      
      /**
       * 演示 懶漢式單例模式,線程不一定安全,同步代碼塊版
       *
       */
      public class Demo {
          public static void main(String[] args) {
              Singleton singleton1 = Singleton.getSingleTon();
              Singleton singleton2 = Singleton.getSingleTon();
              System.out.println(singleton1 == singleton2); // 由于獲取的為同一個對象,所以輸出為true
          }
      }
      
      /**
       * 懶漢式單例模式,線程不一定安全,同步代碼塊版
       */
      class Singleton {
          // 在類的內(nèi)部聲明一個實例對象
          private static Singleton singleton;
      
          /**
           * 構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
           */
          private Singleton() {
          }
      
          /**
           * 向外暴露一個靜態(tài)的公共方法用于獲取實例對象,在方法內(nèi)部加個同步代碼塊。 當(dāng)調(diào)用該方法時,才去檢查并創(chuàng)建一個實例對象。
           * 
           * @return 實例對象
           */
          public static Singleton getSingleTon() {
              if (singleton == null) {
                  synchronized (Singleton.class) {
                      singleton = new Singleton();
                  }
              }
              return singleton;
          }
      }

      (3)優(yōu)缺點:
        優(yōu)點:優(yōu)化了了上例 懶漢式單例模式(線程安全,同步方法) 的效率問題。
        缺點:能滿足大部分線程安全的情況,但是若線程A與線程B并發(fā)執(zhí)行到 if (singleton == null),此時同步代碼塊的作用就不存在了, 會產(chǎn)生多個實例對象。

       

      8、雙重檢查(Double Check)

      (1)步驟:
        step1:構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
        step2:在類的內(nèi)部聲明實例對象,并使用volatile關(guān)鍵字(保證可見性,且防止因JVM指令重排使代碼執(zhí)行順序不對,從而導(dǎo)致代碼執(zhí)行有誤)。
        step3:向外暴露一個靜態(tài)的公共方法(在靜態(tài)方法內(nèi)部定義一個代碼塊,解決同步問題)用于獲取實例對象,在調(diào)用該方法時,才去創(chuàng)建實例對象。在上例 懶漢式單例模式(同步代碼塊方法,線程不一定安全) 的基礎(chǔ)上,給同步代碼塊內(nèi)部加個檢查處理。
      (2)代碼實現(xiàn):

      package singleton.pattern.demo6;
      
      /**
       * 演示 單例模式,雙重檢查版
       *
       */
      public class Demo {
          public static void main(String[] args) {
              Singleton singleton1 = Singleton.getSingleTon();
              Singleton singleton2 = Singleton.getSingleTon();
              System.out.println(singleton1 == singleton2); // 由于獲取的為同一個對象,所以輸出為true
          }
      }
      
      /**
       * 單例模式,雙重檢查版
       */
      class Singleton {
          // 在類的內(nèi)部聲明一個實例對象
          private static volatile Singleton singleton;
      
          /**
           * 構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
           */
          private Singleton() {
          }
      
          /**
           * 向外暴露一個靜態(tài)的公共方法用于獲取實例對象,在方法內(nèi)部加個同步代碼塊,在代碼塊內(nèi)部增加一個檢查處理。 當(dāng)調(diào)用該方法時,才去檢查并創(chuàng)建一個實例對象。
           * 
           * @return 實例對象
           */
          public static Singleton getSingleTon() {
              if (singleton == null) {
                  synchronized (Singleton.class) {
                      if (singleton == null) {
                          singleton = new Singleton();
                      }
                  }
              }
              return singleton;
          }
      }

      (3)優(yōu)缺點:
        優(yōu)點:線程安全,延遲加載,效率高。常用于多線程開發(fā)。

       

      9、靜態(tài)內(nèi)部類

      (1)步驟:
        step1:構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
        step2:在類的內(nèi)部定義一個靜態(tài)內(nèi)部類(只有被調(diào)用時,才會被加載),并在內(nèi)部類中實例化對象。
        step3:向外暴露一個靜態(tài)的公共方法,并在方法中調(diào)用靜態(tài)內(nèi)部類,用于獲取實例對象。
      (2)代碼實現(xiàn):

      package singleton.pattern.demo7;
      
      /**
       * 演示 單例模式,靜態(tài)內(nèi)部類版
       *
       */
      public class Demo {
          public static void main(String[] args) {
              Singleton singleton1 = Singleton.getSingleTon();
              Singleton singleton2 = Singleton.getSingleTon();
              System.out.println(singleton1 == singleton2); // 由于獲取的為同一個對象,所以輸出為true
          }
      }
      
      /**
       * 單例模式,靜態(tài)內(nèi)部類版
       */
      class Singleton {
          /**
           * 構(gòu)造器私有化(防止通過new創(chuàng)建實例對象)
           */
          private Singleton() {
          }
      
          /**
           * 靜態(tài)內(nèi)部類,在被調(diào)用的時候才會被加載,實現(xiàn)懶加載。 且內(nèi)部使用靜態(tài)常量實例化一個對象,保證了線程安全問題。
           */
          public static class SingleTonInstance {
              public static final Singleton INSTANCE = new Singleton();
          }
      
          /**
           * 向外暴露一個靜態(tài)的公共方法用于獲取實例對象,在方法內(nèi)部加個同步代碼塊,在代碼塊內(nèi)部增加一個檢查處理。 當(dāng)調(diào)用該方法時,才去檢查并創(chuàng)建一個實例對象。
           * 
           * @return 實例對象
           */
          public static Singleton getSingleTon() {
              return SingleTonInstance.INSTANCE; // 調(diào)用靜態(tài)內(nèi)部類的靜態(tài)屬性
          }
      }

      (3)優(yōu)缺點:
        優(yōu)點:利用JVM的類加載機制,保證了實例化對象時只有一個線程,從而線程安全。在被調(diào)用時靜態(tài)內(nèi)部類才會被加載并實例化對象,從而實現(xiàn)懶加載,效率高。

      (4)UML圖:

       

      10、枚舉

      (1)步驟:
        step1:定義一個枚舉類型。
        step2:調(diào)用即可
      (2)代碼實現(xiàn):

      package singleton.pattern;
      
      /**
       * 演示 單例模式,枚舉版
       *
       */
      public class Demo {
          public static void main(String[] args) {
              SingleTon singleton1 = SingleTon.INSTACNE;
              SingleTon singleton2 = SingleTon.INSTACNE;
              System.out.println(singleton1 == singleton2); // 由于獲取的為同一個對象,所以輸出為true
          }
      }
      
      /**
       * 單例模式,枚舉版
       */
      enum SingleTon {
          INSTACNE;
          public void show() {
              System.out.println("hello world");
          }
      }

      (3)優(yōu)缺點:
        優(yōu)點:使用枚舉類型創(chuàng)建(enum本質(zhì)是個繼承java.lang.Enum類的final class),保證線程安全,且可以防止反序列化重新創(chuàng)建新的對象。

       

      11、JDK中的單例模式舉例(Runtime)

      (1)部分源碼

      public class Runtime {
          private static Runtime currentRuntime = new Runtime();
      
          /**
           * Returns the runtime object associated with the current Java application.
           * Most of the methods of class <code>Runtime</code> are instance
           * methods and must be invoked with respect to the current runtime object.
           *
           * @return  the <code>Runtime</code> object associated with the current
           *          Java application.
           */
          public static Runtime getRuntime() {
              return currentRuntime;
          }
      
          /** Don't let anyone else instantiate this class */
          private Runtime() {} 
      }

      (2)可以看到上述代碼中采用的是 餓漢式單例模式(靜態(tài)變量版)。

      12、單例模式使用注意

      (1)當(dāng)頻繁創(chuàng)建、銷毀某個對象時,可以采用單例模式。
      (2)使用單例模式時,需調(diào)用相關(guān)方法獲取實例,而不是通過new。
      (3)當(dāng)創(chuàng)建對象消耗資源過多時,但又經(jīng)常使用時,可以采用單例模式創(chuàng)建。

       

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多