一、單例模式1、什么是單例模式采取一定的方法,使程序中的某個(gè)類只存在一個(gè)實(shí)例對(duì)象,且該類對(duì)外提供一個(gè)獲取該對(duì)象的方法(一般為靜態(tài)方法)。 2、單例模式分類(1)餓漢式(2種寫(xiě)法,線程安全) (2)懶漢式(3種寫(xiě)法) (3)雙重檢查(推薦使用) 3、餓漢式單例模式(靜態(tài)常量版)(1)步驟: 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); // 由于獲取的為同一個(gè)對(duì)象,所以輸出為true } } /** * 餓漢式單例模式,靜態(tài)變量版 */ class Singleton { // 在類的內(nèi)部創(chuàng)建實(shí)例對(duì)象。使用靜態(tài)變量,只被加載一次。 private static Singleton singleton = new Singleton(); /** * 構(gòu)造器私有化(防止通過(guò)new創(chuàng)建實(shí)例對(duì)象) */ private Singleton() { } /** * 向外暴露一個(gè)靜態(tài)的公共方法用于獲取實(shí)例對(duì)象。 * * @return 實(shí)例對(duì)象 */ public static Singleton getSingleTon() { return singleton; } } (3)優(yōu)缺點(diǎn): (4)UML圖:
4、餓漢式單例模式(靜態(tài)代碼塊)(1)步驟: 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); // 由于獲取的為同一個(gè)對(duì)象,所以輸出為true } } /** * 餓漢式單例模式,靜態(tài)代碼塊版 */ class Singleton { // 在類的內(nèi)部聲明一個(gè)實(shí)例對(duì)象 private static Singleton singleton; static { // 在代碼塊中實(shí)例化一個(gè)對(duì)象,同樣只加載一次 singleton = new Singleton(); } /** * 構(gòu)造器私有化(防止通過(guò)new創(chuàng)建實(shí)例對(duì)象) */ private Singleton() { } /** * 向外暴露一個(gè)靜態(tài)的公共方法用于獲取實(shí)例對(duì)象。 * * @return 實(shí)例對(duì)象 */ public static Singleton getSingleTon() { return singleton; } } (3)優(yōu)缺點(diǎn)同上例 餓漢式單例模式(靜態(tài)常量版) 5、懶漢式單例模式(線程不安全)(1)步驟: 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); // 由于獲取的為同一個(gè)對(duì)象,所以輸出為true } } /** * 懶漢式單例模式,線程不安全版 */ class Singleton { // 在類的內(nèi)部聲明一個(gè)實(shí)例對(duì)象 private static Singleton singleton; /** * 構(gòu)造器私有化(防止通過(guò)new創(chuàng)建實(shí)例對(duì)象) */ private Singleton() { } /** * 向外暴露一個(gè)靜態(tài)的公共方法用于獲取實(shí)例對(duì)象。 當(dāng)調(diào)用該方法時(shí),才去檢查并創(chuàng)建一個(gè)實(shí)例對(duì)象。 * * @return 實(shí)例對(duì)象 */ public static Singleton getSingleTon() { if (singleton == null) { singleton = new Singleton(); } return singleton; } } (3)優(yōu)缺點(diǎn): 6、懶漢式單例模式(線程安全,同步方法)(1)步驟: 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); // 由于獲取的為同一個(gè)對(duì)象,所以輸出為true } } /** * 懶漢式單例模式,線程安全,同步方法版 */ class Singleton { // 在類的內(nèi)部聲明一個(gè)實(shí)例對(duì)象 private static Singleton singleton; /** * 構(gòu)造器私有化(防止通過(guò)new創(chuàng)建實(shí)例對(duì)象) */ private Singleton() { } /** * 向外暴露一個(gè)靜態(tài)的公共方法用于獲取實(shí)例對(duì)象,并給方法加個(gè)synchronized關(guān)鍵字,解決同步的問(wèn)題。 * 當(dāng)調(diào)用該方法時(shí),才去檢查并創(chuàng)建一個(gè)實(shí)例對(duì)象。 * * @return 實(shí)例對(duì)象 */ public static synchronized Singleton getSingleTon() { if (singleton == null) { singleton = new Singleton(); } return singleton; } } (3)優(yōu)缺點(diǎn):
7、懶漢式單例模式(同步代碼塊方法,線程不一定安全)(1)步驟: 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); // 由于獲取的為同一個(gè)對(duì)象,所以輸出為true } } /** * 懶漢式單例模式,線程不一定安全,同步代碼塊版 */ class Singleton { // 在類的內(nèi)部聲明一個(gè)實(shí)例對(duì)象 private static Singleton singleton; /** * 構(gòu)造器私有化(防止通過(guò)new創(chuàng)建實(shí)例對(duì)象) */ private Singleton() { } /** * 向外暴露一個(gè)靜態(tài)的公共方法用于獲取實(shí)例對(duì)象,在方法內(nèi)部加個(gè)同步代碼塊。 當(dāng)調(diào)用該方法時(shí),才去檢查并創(chuàng)建一個(gè)實(shí)例對(duì)象。 * * @return 實(shí)例對(duì)象 */ public static Singleton getSingleTon() { if (singleton == null) { synchronized (Singleton.class) { singleton = new Singleton(); } } return singleton; } } (3)優(yōu)缺點(diǎn):
8、雙重檢查(Double Check)(1)步驟: 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); // 由于獲取的為同一個(gè)對(duì)象,所以輸出為true } } /** * 單例模式,雙重檢查版 */ class Singleton { // 在類的內(nèi)部聲明一個(gè)實(shí)例對(duì)象 private static volatile Singleton singleton; /** * 構(gòu)造器私有化(防止通過(guò)new創(chuàng)建實(shí)例對(duì)象) */ private Singleton() { } /** * 向外暴露一個(gè)靜態(tài)的公共方法用于獲取實(shí)例對(duì)象,在方法內(nèi)部加個(gè)同步代碼塊,在代碼塊內(nèi)部增加一個(gè)檢查處理。 當(dāng)調(diào)用該方法時(shí),才去檢查并創(chuàng)建一個(gè)實(shí)例對(duì)象。 * * @return 實(shí)例對(duì)象 */ public static Singleton getSingleTon() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } } (3)優(yōu)缺點(diǎn):
9、靜態(tài)內(nèi)部類(1)步驟: 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); // 由于獲取的為同一個(gè)對(duì)象,所以輸出為true } } /** * 單例模式,靜態(tài)內(nèi)部類版 */ class Singleton { /** * 構(gòu)造器私有化(防止通過(guò)new創(chuàng)建實(shí)例對(duì)象) */ private Singleton() { } /** * 靜態(tài)內(nèi)部類,在被調(diào)用的時(shí)候才會(huì)被加載,實(shí)現(xiàn)懶加載。 且內(nèi)部使用靜態(tài)常量實(shí)例化一個(gè)對(duì)象,保證了線程安全問(wèn)題。 */ public static class SingleTonInstance { public static final Singleton INSTANCE = new Singleton(); } /** * 向外暴露一個(gè)靜態(tài)的公共方法用于獲取實(shí)例對(duì)象,在方法內(nèi)部加個(gè)同步代碼塊,在代碼塊內(nèi)部增加一個(gè)檢查處理。 當(dāng)調(diào)用該方法時(shí),才去檢查并創(chuàng)建一個(gè)實(shí)例對(duì)象。 * * @return 實(shí)例對(duì)象 */ public static Singleton getSingleTon() { return SingleTonInstance.INSTANCE; // 調(diào)用靜態(tài)內(nèi)部類的靜態(tài)屬性 } } (3)優(yōu)缺點(diǎn): (4)UML圖:
10、枚舉(1)步驟: 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); // 由于獲取的為同一個(gè)對(duì)象,所以輸出為true } } /** * 單例模式,枚舉版 */ enum SingleTon { INSTACNE; public void show() { System.out.println("hello world"); } } (3)優(yōu)缺點(diǎn):
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)建、銷毀某個(gè)對(duì)象時(shí),可以采用單例模式。
|
|