Java23種設計模式之-----單例模式

一、什麼是單例模式?
單例模式是一種對象創建型模式,使用單例模式,可以保證爲一個類只生成唯一的實例對象。也就是說,在整個程序空間中,該類只存在一個實例對象。其實,GoF對單例模式的定義是:保證一個類、只有一個實例存在,同時提供能對該實例加以訪問的全局訪問方法。
二、爲什麼要使用單例模式呢?
在應用系統開發中,我們常常有以下需求:
(1)、在多個線程之間,比如servlet環境,共享同一個資源或者操作同一個對象
(2)、在整個程序空間使用全局變量,共享資源
(3)、大規模系統中,爲了性能的考慮,需要節省對象的創建時間等等。
因爲SingIeton模式可以保證爲一個類只生成唯一的實例對象,所以這些情況,SingIeton模式就派上用場了。
三、單例模式的實現
(1)、餓漢式
(2)、懶漢式
(3)、雙重檢查
四、代碼實現:
(1)、餓漢模式:
創建Person類

package com.renxin.singleton;

public class Person {

    public static final Person person = new Person();

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    //構造函數私有化
    private Person() {

    }
    //提供一個全局的靜態方法
    public static Person getPerson() {
        return person;
    }

}

創建測試類MainClass

package com.renxin.singleton;

public class MainClass {

    public static void main(String[] args) {
        Person per = Person.getPerson();
        Person per2 = Person.getPerson();
        per.setName("zhangsan");
        per2.setName("lisi");

        System.out.println(per.getName());
        System.out.println(per.getName());

    }

}

控制檯打印結果爲:

lisi
lisi

(2)、懶漢式
創建Persion2類:

package com.renxin.singleton;

public class Person2 {

    private String name;
    private static Person2 person;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    //構造函數私有化
    private Person2() {

    }
    //提供一個全局的靜態方法
    public static Person2 getPerson() {
        if(person == null) {
            person = new Person2();
        }
        return person;
    }

}

創建測試類MainClass:

package com.renxin.singleton;

public class MainClass {

    public static void main(String[] args) {
        Person2 per = Person2.getPerson();
        Person2 per2 = Person2.getPerson();
        per.setName("zhangsan");
        per2.setName("lisi");

        System.out.println(per.getName());
        System.out.println(per.getName());

    }

}

控制檯打印結果爲:

lisi
lisi

五、懶漢式和餓漢式比較:
餓漢式是線程安全的,在類創建的同時就已經創建好一個靜態的對象供系統使用,以後不在改變。
懶漢式如果在創建實例對象時不加上synchronized則會導致對對象的訪問不是線程安全的。
推薦使用餓漢式:
從實現方式來講他們最大的區別就是懶漢式是延時加載,他是在需要的時候才創建對象,而餓漢式在虛擬機啓動的時候就會創建,餓漢式無需關注多線程問題、寫法簡單明瞭、能用則用。但是它是加載類時創建實例、所以如果是一個工廠模式、緩存了很多實例、那麼就得考慮效率問題,因爲這個類一加載則把所有實例不管用不用一塊創建。
懶漢式的優點是延時加載、缺點是應該用同步(想改進的話現在還是不可能,比如double-check)、其實也可以不用同步、看你的需求了,多創建一兩個無引用的廢對象其實也沒什麼大不了。
(3)、雙重檢查:

package com.renxin.singleton;

public class Person3 {

    private String name;
    private static Person3 person;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    //構造函數私有化
    private Person3() {

    }
    //提供一個全局的靜態方法
    public static Person3 getPerson() {
        if(person == null) {
            synchronized (Person3.class) {
                if(person == null) {
                    person = new Person3();
                }
            }
        }
        return person;
    }

}

雙重檢查說白了就是對懶漢式的改進!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章