1. 程式人生 > >java架構之路-(設計模式)五種建立型模式之單例模式

java架構之路-(設計模式)五種建立型模式之單例模式

  設計模式自身一直不是很瞭解,但其實我們時刻都在使用這些設計模式的,java有23種設計模式和6大原則。

設計模式是一套被反覆使用、多數人知曉的、經過分類編目的、程式碼設計經驗的總結。使用設計模式是為了可重用程式碼、讓程式碼更容易被他人理解、保證程式碼可靠性、程式的重用性。

其中包含

建立型模式,共五種:單例模式、工廠方法模式、抽象工廠模式、建造者模式、原型模式。

結構型模式,共七種:介面卡模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。

行為型模式,共十一種:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、直譯器模式。

我們今天就來說說我們的建立型模式

單例模式:是Java中最簡單的設計模式之一。它提供了一種建立物件的最佳方式。

這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。這個類提供了一種訪問其唯一的物件的方式,可以直接訪問,不需要例項化該類的物件。

用一種其它的方式來記憶吧,單例模式猶如我們吃的土豆,只有一個土豆,你叫他土豆也行,叫他馬鈴薯也可以,還可以叫Potato,但最終還是那一個土豆。

注意:

1、單例類只能有一個例項。

2、單例類必須自己建立自己的唯一例項。

3、單例類必須給所有其他物件提供這一例項。

程式碼實現:

  餓漢式單例模式:

package Single;

public class CarBean {

    public static CarBean carBean = new CarBean();

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //關閉構造方法.防止New物件
    private CarBean() {
        System.out.println("CarBean構造方法只走一次");
    }

    public static CarBean getInstance() {
        return carBean;
    }

}
package Single;

public class MainTest {
    /**
     * 餓漢式靜態常量式單例模式
     * 優點:這種寫法在JVM裝載類的時候就例項化了,避免了執行緒同步的問題
     * 缺點:在類裝載的時候就例項化,沒有達到延時載入的效果,造成記憶體浪費
     * @param args
     */
    public static void main(String[] args) {
        CarBean car1 = CarBean.getInstance();
        CarBean car2 = CarBean.getInstance();
        car1.setName("蘭博基尼");
        car2.setName("瑪莎拉蒂");
        System.out.println(car1.getName());
        System.out.println(car2.getName());
    }
}

  懶漢式單例模式(非同步):

package Single2;

public class CarBean {

    public static CarBean carBean  = null;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //關閉構造方法.防止New物件
    private CarBean() {
        System.out.println("CarBean構造方法只走一次");
    }

    public static CarBean getInstance() {
        if(carBean == null) {
            carBean = new CarBean();
        }
        return carBean;
    }

}
package Single2;

public class MainTest {
    /**
     * 懶漢式單例模式:非同步
     * 優點:在呼叫的時候初始化該單例
     * 缺點:並非執行緒同步,不建議使用
     * @param args
     */
    public static void main(String[] args) {
        CarBean car1 = CarBean.getInstance();
        CarBean car2 = CarBean.getInstance();
        car1.setName("蘭博基尼");
        car2.setName("瑪莎拉蒂");
        System.out.println(car1.getName());
        System.out.println(car2.getName());
    }
}

  懶漢式單例模式(同步): 

package Single3;

public class CarBean {

    public static CarBean carBean = null;

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    //關閉構造方法.防止New物件
    private CarBean() {
        System.out.println("CarBean構造方法只走一次");
    }

    /**
     * 方法1
     * 該方式使用synchronized同步鎖將整個方法同步 實現執行緒同步 但同步整個方法在高併發的情況下會造成阻塞效率低下
     * 不推薦使用
     * @return
     */
    public static synchronized CarBean getInstance1() {
        if (carBean == null) {
            carBean = new CarBean();
        }
        return carBean;
    }

    /**
     * 方法2使用synchronized同步例項化改單例的程式碼塊;但該方法不能完全實現同步,可能會產生多個例項;
     * 例如:在第一次建立時多個執行緒同時進入if(lazySingleton == null) 則會產生多個例項
     * 不推薦使用
     * @return
     */
    public static CarBean getInstance2() {
        if (carBean == null) {
            synchronized (CarBean.class) {
                carBean = new CarBean();
            }
        }
        return carBean;
    }

    /**
     * 方法3:雙重檢查法,同步程式碼塊中再次檢查一次是否w為null解決了上述問題   推薦使用
     */
    public static CarBean getInstance3() {
        if (carBean == null) {
            synchronized (CarBean.class) {
                if (carBean == null) {
                    carBean = new CarBean();
                }
            }
        }
        return carBean;
    }

}

裡面具體的優缺點我都寫在程式碼註釋裡了。

後面會把每一個模式都寫一