<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                **寫在前邊:**辛辛苦苦寫了好幾天終于能有一篇發到首頁上了,其中的艱辛就不必多說了,我不是專家不發能首頁,好多文章博樂也都不看,比起首頁上那些空洞無味的文章,我覺得我的博客對一部分人能起到幫助的作用,如果您覺得我寫的還可以就頂一下吧,您的支持是我最大的動力! ### 一、模式定義 單例模式(Singleton Pattern):單例模式確保某一個類只有一個實例,而且自行實例化并向整個系統提供這個實例,這個類稱為單例類,它 提供全局訪問的方法。 單例模式的要點有三個:一是某個類只能有一個實例;二是它必須自行創建這個實例;三是它必須自行向整個系統提供這個實例。單例模式 是一種對象創建型模式。單例模式又名單件模式或單態模式。 ### 二、模式結構 ![這里寫圖片描述](https://box.kancloud.cn/2016-04-20_57175852e1d94.jpg "") 我們可以看到單例模式與我們之前所講的工廠模式不同,它只有一個Singleton角色,并且這個類自行創建自己的實例,并向系統提供這個實 例,可以注意到我沒有在圖中吧實例的建造個數限制為1個,這一點我們后邊會講到多例模式。 單例模式分為懶漢式的和餓漢式,有的地方也會講登記式的單例模式,下面我們就一起來學習一下這三種單例模式。 ### 三、餓漢式的單例模式 餓漢式單例模式是Java語言中實現起來最為簡單的單例模式,我們通過代碼來看一下。 ~~~ package com.designpattern.singleton; public class EagerSingleton { /** * 直接創建一個本類的對象 */ private static final EagerSingleton eagerSingleton = new EagerSingleton(); /** * 覆蓋默認的構造方法,將默認的構造方法聲明為私有的,防止其他類直接創建對象 */ private EagerSingleton(){} /** * 提供一個工廠方法來返回本類的唯一對象 * @return */ public static EagerSingleton getInstance(){ return eagerSingleton; } } ~~~ 餓漢式單例模式就是一開始就自己創建一個私有的靜態的本類對象,當這個類被加載時,靜態變量eagerSingleton就會被初始化,這時這個 類的私有構造方法就會被調用。這個時候,單例類的唯一實例就被創建出來了。但需要獲得單例類的對象是就調用getInstance方法。 需要注意的一點就是單例類的構造方法一定要聲明為私有的,否則其他類就可以利用構造方法直接創建對象,使單例類不再是只有一個唯一 的實例。 另外,值得一提的是,由于構造方法是私有的,因此此類不能被繼承。 餓漢式單例模式在自己加載時就將自己實例化,所以從資源利用效率的角度來講,餓漢式單例模式不如懶漢式單例模式節省資源,但是餓漢 式單例模式的速度更快一些。 ### 四、懶漢式的單例模式 懶漢式單例模式與餓漢式稍有不同,下面看一下代碼: ~~~ package com.designpattern.singleton; public class LazySingleton { /** * 單例類的唯一實例,但是不是加載時初始化 */ private static LazySingleton lazySingleton = null; /** * 覆蓋原有的默認構造方法,聲明為私有的,防止其他類直接使用構造方法創建單例類對象,同時也使子類無法繼承 */ private LazySingleton() { } /** * 線程互斥的獲取實例 * @return */ public static synchronized LazySingleton getInstance() { /** * 如果實例為空就創建實例,創建的語句只會執行一次 */ if (lazySingleton == null) { lazySingleton = new LazySingleton(); } return lazySingleton; } } ~~~ 從代碼我們可以看出,懶漢式單例模式的創建對象是在第一次企圖獲得單例類的對象時。另外我們再getInstance方法中使用了 synchronization關鍵字,這是防止出現race condition,使兩個線程new出來兩個單例類的實例。構造方法同樣是私有的,這也決定了子類 不能繼承自這個類。 懶漢式單例模式與餓漢式單例模式相比,更節省資源,但是必須處理好在多個線程同時首次引用此類時的訪問限制問題,特別是當單例類作 為資源控制器在實例化時必然涉及資源初始化,而資源初始化很有可能耗費時間,這就意味著出現多個線程同時首次引用此類的幾率變得較 大。 ### 五、登記式的單例模式 為了克服餓漢式單例模式以及懶漢式單例模式類均不可繼承的缺點,產生了一種新的模式——登記式單例模式。 登記式的單例模式中父類中有一個集合,用來存儲所有的子類的實例,當一個子類創建時,必須在父類的中登記,也就是把自己的實例加入 到父類的集合中,當其他類想要獲取子類的實例時,就到父類的集合中查找,找到了就返回,如果找不到就創建這個子類的唯一實例。 這是父類的代碼。 ~~~ package com.designpattern.singleton; import java.util.HashMap; public class RegSingleton { /** * 建立一個HashMap來存儲子類的完整類名和子類的實例 */ private static HashMap registry = new HashMap<String, RegSingleton>(); /** * 首先將本類的實例加入到HashMap中 */ static{ RegSingleton x = new RegSingleton(); registry.put(x.getClass().getName(), x); } /** * 構造方法不再是private的了,所以子類可以繼承了 */ protected RegSingleton(){ } /** * 根據子類傳來的類名返回相應的實例 * @param name 想要獲得的類的完整類名 * @return */ public static RegSingleton getInstance(String name){ /** * 提供默認的類 */ if(name == null){ name = "com.designpattern.singleton.RegSingleton"; } /** * 第一次引用這個類時創建類的實例,利用了反射機制 */ if(registry.get(name) == null){ try{ registry.put(name, Class.forName(name).newInstance()); }catch(Exception e){ e.printStackTrace(); } } /** * 返回子類想要的類的實例 */ return (RegSingleton)registry.get(name); } } ~~~ 這是子類的代碼。 ~~~ package com.designpattern.singleton; public class RegSingletonChild extends RegSingleton{ /** * 構造方法必須是公有的,否則父類無法產生子類的對象 */ public RegSingletonChild(){} /** * 工廠方法,獲取本類的唯一實例,實際上是借助了父類的getInstance方法 * @return */ public static RegSingletonChild getInstance(){ return (RegSingletonChild)RegSingleton.getInstance("com.designpattern.singleton.RegSingletonChild"); } } ~~~ 登記式的單例模式解決了懶漢式和餓漢式不能繼承的缺點,但是子類中的構造方法變為了public的,所以其他類可以直接通過構造方法創建 類的實例而不用向父類中登記,這是登記式單例模式最大的缺點。 ### 六、什么情況下使用單例模式 - 系統只需要一個實例對象,如系統要求提供一個唯一的序列號生成器,或者需要考慮資源消耗太大而只允許創建一個對象。 - 客戶調用類的單個實例只允許使用一個公共訪問點,除了該公共訪問點,不能通過其他途徑訪問該實例。 - 在一個系統中要求一個類只有一個實例時才應當使用單例模式。反過來,如果一個類可以有幾個實例共存,就需要對單例模式進行改進, 使之成為多例模式 可能有人會將一個系統中需要的“全局”變量放在一個單例類中,這樣做是不對的。首先,單例模式針對的是只能有一個實例的類而不是變 量,其次一個設計得當的系統就不應該有所謂的“全局”變量,這些變量應該放到他們所描述的實體所對應的類中去。將這些變量從他們的 實體類中抽出來,放到一個不相干的單例類中去,使得這些變量產生錯誤的依賴關系和耦合關系。 在資源方面管理方面,單例模式用的更多,比如一臺計算機連接著一臺打印機,那么這個打印機就只有一臺,也只應該有一個實例,試想如 果有兩個打印機的實例,這兩個實例同時操控打印機會出現什么情況,打出來的東西將是亂七八糟的。 所以應該在合適的情況下合理的使用設計模式,而不是一味的追求一個系統利用了多少模式。 ### 七、單例模式的優點和缺點 **單例模式的優點:** - 提供了對唯一實例的受控訪問。因為單例類封裝了它的唯一實例,所以它可以嚴格控制客戶怎樣以及何時訪問它,并為設計及開發團隊提 供了共享的概念。 - 由于在系統內存中只存在一個對象,因此可以節約系統資源,對于一些需要頻繁創建和銷毀的對象,單例模式無疑可以提高系統的性能。 - 允許可變數目的實例。我們可以基于單例模式進行擴展,使用與單例控制相似的方法來獲得指定個數的對象實例。 **單例模式的缺點:** - 由于單例模式中沒有抽象層,因此單例類的擴展有很大的困難。 - 單例類的職責過重,在一定程度上違背了“單一職責原則”。因為單例類既充當了工廠角色,提供了工廠方法,同時又充當了產品角色, 包含一些業務方法,將產品的創建和產品的本身的功能融合到一起。 - 濫用單例將帶來一些負面問題,如為了節省資源將數據庫連接池對象設計為單例類,可能會導致共享連接池對象的程序過多而出現連接池 溢出;現在很多面向對象語言(如Java、C#)的運行環境都提供了自動垃圾回收的技術,因此,如果實例化的對象長時間不被利用,系統會認 為它是垃圾,會自動銷毀并回收資源,下次利用時又將重新實例化,這將導致對象狀態的丟失。 ### 八、模式在JDK中的應用 Java中的Runtime對象就是一個使用單例模式的例子。在每一個Java應用程序里面,都有唯一的一個Runtime對象,通過這個對象應用程序可 以與其運行環境發生相互作用。 Runtime類提供一個靜態工廠方法getRuntime(): `public static Runtime getRuntime();` 通過調用次方法,可以獲得Runtime類唯一的一個實例: `Runtime rt = Runtime.getRuntime();` ### 九、擴展:多例模式 單例是只有一個類實例,自然多例模式就是有多個類的實例了。下面就以有兩個實例為例講一下。 ~~~ package com.designpattern.singleton; import java.util.Random; public class Die { /** * 兩個類實例 */ private static Die die1 = new Die(); private static Die die2 = new Die(); /** * 私有的構造方法 */ private Die(){} /** * 根據用戶使用的標號來決定返回哪一個對象 * @param witchOne * @return */ public static Die getInstance(int witchOne){ if(witchOne == 1) return die1; else return die2; } /** * 使用對象產生隨機數 * @return */ public synchronized int dice(){ Random rand = new Random(); return rand.nextInt(6)+1; } } ~~~ ~~~ package com.designpattern.singleton; public class Client { public static void main(String[] args){ Die die1 = Die.getInstance(1); Die die2 = Die.getInstance(2); System.out.println(die1.dice()); System.out.println(die2.dice()); } } ~~~ 我們看到多例模式的多例類中有多于一個對象實例,究竟返回哪一個對象取決于程序的業務邏輯。 源碼下載:[http://download.csdn.net/detail/xingjiarong/9297315](http://download.csdn.net/detail/xingjiarong/9297315)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看