一、什麼是單例模式 一個類只有一個全局實例 二、補充說明 一般把其構造方法設為私有,另外提供一個可以獲取該實例的靜態方法; 由於java存在反射機制,即使是私有構造方法,也能被外部創建,所以一般的寫法嚴格來講不屬於單例模式;(ps:可以在構造方法內加個靜態flag標誌判斷,保證其只能創建一次) 違背
一、什麼是單例模式
一個類只有一個全局實例
二、補充說明
一般把其構造方法設為私有,另外提供一個可以獲取該實例的靜態方法;
由於java存在反射機制,即使是私有構造方法,也能被外部創建,所以一般的寫法嚴格來講不屬於單例模式;(ps:可以在構造方法內加個靜態flag標誌判斷,保證其只能創建一次)
違背了“單一職責原則”,該類既是工廠又是產品(自己創建了自己);
單例模式可以改造成固定大小的多例模式;
三、角色
只有一個角色,就是單例;
四、Java例子
舉幾個常見的實用的例子
1、在類載入的時候生成對象(如生成該單例對象不耗資源的情況,可以考慮使用)
優點:線程安全;
缺點:不能達到(單例實例在第一次被使用時構建)的效果;
package com.pichen.dp.creationalpattern.singletonpattern.implement1; public class MyPrinter { private static MyPrinter myPrinter = new MyPrinter(); private MyPrinter(){ System.out.println("implements1: created a MyPrint instance."); } public static MyPrinter getInsatnce(){ return myPrinter; } public static void testPrint(){ MyPrinter.getInsatnce().print("hello!"); } public void print(String str){ System.out.println(str); } }
2、單例實例在第一次被使用時構建(單線程環境使用)
優點:單例實例在第一次被使用時構建;
缺點:不加鎖的話,存線上程安全問題,即使加了鎖,對性能也產生了影響;
package com.pichen.dp.creationalpattern.singletonpattern.implement2; public class MyPrinter { private static MyPrinter myPrinter = null; private MyPrinter(){ System.out.println("implements2: created a MyPrint instance."); } public static synchronized MyPrinter getInsatnce(){ if(null == myPrinter){ myPrinter = new MyPrinter(); } return myPrinter; } public static void testPrint(){ System.out.println("hello!"); } public void print(String str){ System.out.println(str); } }
3、靜態內部類(推薦使用)
優點:線程安全;單例實例在第一次被使用時構建;
缺點:暫無發現
package com.pichen.dp.creationalpattern.singletonpattern.implement3; public class MyPrinter { private static class MyPrinterHolder { private static MyPrinter instance = new MyPrinter(); } private MyPrinter(){ System.out.println("implements3: created a MyPrint instance."); } public static MyPrinter getInsatnce(){ return MyPrinterHolder.instance; } public static void testPrint(){ System.out.println("hello!"); } public void print(String str){ System.out.println(str); } }
寫個測試類如下,當我們沒有顯示的調用getInsatnce方法的時候,是不會生成單例對象的;
package com.pichen.dp.creationalpattern.singletonpattern.implement3; import com.pichen.dp.creationalpattern.singletonpattern.implement3.MyPrinter; public class Main { public static void main(String[] args) { // MyPrinter p = MyPrinter.getInsatnce(); // p.print("hello world."); MyPrinter.testPrint(); } }
列印結果:
hello!