【設計模式】單例模式


使用頻率:★★★★☆

一、什么是單例模式

一個類只有一個全局實例

二、補充說明

一般把其構造方法設為私有,另外提供一個可以獲取該實例的靜態方法;

由於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!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM