02_javaSE面試題:單例設計模式

還記得不少年前,面試就讓在白板上寫個單例模式,當時技術渣渣,還寫的是class A.面試官還說,你就不能寫個Singleton.java

面試題

  • 編程題:寫一個Singleton示例

解析

什麼是Singleton?

  • Singleton: 就是指的java中的單例設計模式
  • 單例模式:即某個類在整個系統中只有一個實例對象可被獲取和使用的代碼模式面試

    單例模式的特色

  • 單例類只能有一個實例。
    • 構造函數私有化
  • 單例類必須本身建立本身的惟一實例。
    • 含有一個該類的靜態變量來保存這個惟一實例
  • 單例類必須給全部其餘對象提供這一實例。
    • 對外提供獲取該實例對象的方式

單例模式常見的形式

  • 餓漢式:直接建立對象,不存在線程安全的問題
    • 直接實例化餓漢式(簡潔直觀)
    • 枚舉式(最簡潔)
    • 靜態代碼塊餓漢式(適合複雜實例化)
  • 懶漢式:延遲建立對象
    • 線程不安全 (適合單線程)
    • 線程安全(適合多線程)
    • 靜態內部類形式(適合多線程)

代碼實戰

餓漢式

(1) 直接實例化餓漢式編程

/**
 * 餓漢式(直接建立實例對象)
 * 直接經過類名調用
 *
 * @author kevin
 * @date 2019/7/8 11:23
 */
public class Singleton1 {
    public static final Singleton1 INSTANCE = new Singleton1();

    private Singleton1() {

    }
}

(2)枚舉式設計模式

/**
 * 餓漢式(枚舉)
 *
 * @author kevin
 * @date 2019/7/8 11:29
 */
public enum Singleton2 {
    INSTANCE;
}

(3) 靜態代碼塊安全

import java.io.IOException;
import java.util.Properties;

/**
 * @author kevin
 * @date 2019/7/8 13:35
 */
public class Singleton3 {

    public static final Singleton3 INSTANCE;
    private String info;

    static {
        try {
            Properties properties = new Properties();
            properties.load(Singleton3.class.getClassLoader().getResourceAsStream("sing.properties"));
            INSTANCE = new Singleton3(properties.getProperty("info"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    private Singleton3(String info) {
        this.info = info;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Singleton3{" +
                "info='" + info + '\'' +
                '}';
    }
}

注意:這裏還有個properties文件多線程

info=kevin

測試ide

Singleton3 s = Singleton3.INSTANCE;
 System.out.println(s);

結果函數

Singleton3{info='kevin'}

懶漢式

(1)線程不安全測試

public class Singleton4 {

    private static Singleton4 instance;

    public static Singleton4 getInstance(){
        if(instance == null){
            instance = new Singleton4();
        }
        return instance;
    }
    private Singleton4(){

    }
}

(2) 線程安全this

/**
 * @author kevin
 * @date 2019/7/8 13:56
 */
public class Singleton5 {

    private static Singleton5 instance;

    public static Singleton5 getInstance() {
        if (instance == null) {
            synchronized (Singleton5.class) {
                if (instance == null) {
                    instance = new Singleton5();
                }
            }
        }

        return instance;
    }

    private Singleton5() {

    }
}

(3)靜態內部類 線程安全

/**
 * 靜態內部類不會自動隨着外部類的加載而初始化
 *
 * @author kevin
 * @date 2019/7/8 13:56
 */
public class Singleton6 {
    private static class Inner {
        private static final Singleton6 INSTANCE = new Singleton6();
    }

    public static Singleton6 getInstance() {
        return Inner.INSTANCE;
    }

    private Singleton6() {

    }
}

注意:靜態內部類不會自動隨着外部類的加載而初始化

總結

  • 餓漢式,枚舉最簡單
  • 懶漢式,靜態內部類最簡單

好了,玩的開心。

相關文章
相關標籤/搜索