設計模式-單例模式及多種實現

xl_echo編輯整理,歡迎轉載,轉載請聲明文章來源。歡迎添加echo微信(微信號:t2421499075)交流學習。
百戰不敗,依不自稱常勝,百敗不頹,依能奮力前行。——這纔是真正的堪稱強大!!


單例模式

單例模式(Singleton Pattern)是Java中最簡單的設計模式之一,屬於創建型,一般都用於保證唯一性的創建,這也是他最大的特點(保證全局只有唯一的一個實例),並且提供一個全局的訪問點。

單例有以下幾種形式

  • 餓漢式
  • 懶漢(存在線程安全問題)
  • 註冊登記式
  • 枚舉式
  • 序列化(存在線程安全問題)
  • 反序列化(存在線程安全問題)
創建單例一般要做一下幾點:
  • 私有化構造器
  • 實例的創建
  • 提供靜態的對外訪問的單例引用

餓漢式:不管用戶是否使用,類加載的時候就會new一個對象出來,這樣有效的避免了線程的安全問題。但是它也有對應的缺點,如果餓漢式使用較多,會對資源暫用較多。因爲不管用不用該類,都創建了對象。
餓漢式代碼示例如下:

public class HungryTest {
    private HungryTest(){}
    private static final HungryTest hungryTest = new HungryTest();
    public static HungryTest getInstance(){
        return hungryTest;
    }
}
public class HungryTest2 {
    private static final HungryTest2 HUNGRY_TEST_2;
    private HungryTest2(){}
    static {
        HUNGRY_TEST_2 = new HungryTest2();
    }
    public static HungryTest2 getInstance(){
        return HUNGRY_TEST_2;
    }
}

懶漢式和餓漢式相反:默認類在加載的時候是不會進行對象創建的,一般是在用戶使用的時候進行創建。如果使用比較多的情況下,可能會有併發的情況出現,這樣就沒法保證唯一對象。解決這個問題的辦法有,直接在創建對象的方法上面添加synchronize,但是加上這個會出現新的問題那就是性能問題。

懶漢式代碼示例如下:

//同步鎖,但是性能略低
public class LazyOne {
    private LazyOne(){}
    private LazyOne lazyOne = null;
    public synchronized LazyOne getInstatnce(){
        if (lazyOne == null) {
            lazyOne = new LazyOne();
        }
        return lazyOne;
    }
}

註冊式代碼示例如下:

public class RegisterMap {
    private RegisterMap() {}
    private static Map<String, Object> map = new HashMap<>();
    public static RegisterMap getInstance(String name) {
        if (ObjectUtils.isEmpty(name)) {
            name = RegisterMap.class.getName();
        }
        if (ObjectUtils.isEmpty(map.get(name))) {
            map.put(name, new RegisterMap());
        }
        return (RegisterMap) map.get(name);
    }
}

註冊枚舉式代碼示例如下:

public enum EnumSingleton {
    BLACK, WIRTH;
    public void getInstance() {}
}

序列化代碼示例如下:

public class SerializationSingleton implements Serializable {
    private SerializationSingleton(){}
    private static SerializationSingleton SERIALIZATION_SINGLETON = new SerializationSingleton();
    public static SerializationSingleton getInstance(){
        return SERIALIZATION_SINGLETON;
    }
    /**
     * 序列化與反序列化的協議,能夠保證單例線程安全。
     */
    private Object readResolve(){
        return SERIALIZATION_SINGLETON;
    }
}

容器式單例代碼示例如下

public class ContainerSingleton {
    private ContainerSingleton(){}
    private static Map<String, Object> ioc = new ConcurrentHashMap<>();
    public static Object getBean(String className) {
        synchronized (ioc){
            if (!ioc.containsKey(className)) {
                Object obj = null;
                try {
                    obj = Class.forName(className).newInstance();
                    ioc.put(className, obj);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return obj;
            }
            return ioc.get(className);
        }
    }
}
public class Person {}
public class ContainerSingletonTest {
    public static void main(String[] args) {
        IntStream.range(0, 10).forEach(it -> {
            Thread thread = new Thread(() -> {
                Object instance = ContainerSingleton.getBean("com.echo.demo.designPatterns.singletonDesignPatterns.container.Person");
                System.out.println(Thread.currentThread().getName() + ":" + instance);
            });
            thread.start();
        });
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章