Java的設計模式足有23種之多!!
Java的設計模式足有23種之多,
分類
按行為屬性,結構屬性可以分為三大類
建立型模式(5種):單例模式、工廠模式、抽象工廠模式、建造者模式、原型模式
結構性模式(7種):介面卡模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式
行為型模式(11種):策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、直譯器模式
常用的幾種設計模式
單例模式是非常常用的設計模式,他確保一個類只有一個物件,並且這個物件是自己建立的(通過IoC控制反轉實現自己建立)。外界可以獲取和使用這個物件
單例模式建立物件有“懶漢式”,“餓漢式”,單例模式構造方法私有化,外界無法建立,只能獲取,下面兩種單例實現:
餓漢式
package demo_singleton;
public class SingletonHungry {
//程式一載入就立馬建立/實現物件
private static SingletonHungry singletonhunary = new SingletonHungry();
private SingletonHungry() {
}
public static SingletonHungry getinstance() {
return singletonhunary;
}
}
懶漢式
package demo_singleton; /*懶漢式的單例模式,有執行緒安全問題,當多執行緒訪問的時候,會出現多個例項*/ public class SingletonLazy { private static SingletonLazy instance = null; private SingletonLazy() { } public static SingletonLazy getInstance() { if (instance == null) { instance = new SingletonLazy(); } return instance; } }
載入期是早於執行期的,類載入發生在執行期,執行緒生成執行實在執行期,所以“餓漢式”不會遇到執行緒安全問題,“懶漢式”是getInstance獲取物件時才建立物件(獲取物件這行為是執行期的行為),如果此時剛好有多個執行緒同時呼叫getInstance()方法,就會發生執行緒併發安全問題。
“懶漢式”執行緒安全測試辦法
同包下建一個測試類,繼承Thread介面,重寫run()方法,執行列印 懶漢式的getInstance()。建立多個執行緒,並start();
結果顯示 物件的地址,如果多個執行緒輸出的地址不一樣,這說明發生執行緒併發問題。就不是我們想要的單例模式了。
“懶漢式”單例模式執行緒併發問題優化
優化一
解決執行緒併發問題,首先想到的辦法是同步,加上synchronized關鍵字
同步方法:
public static synchronized SingletonLazy1 getInstance(){
同步塊:
public static SingletonLazy2 getInstance() {
synchronized (SingletonLazy2.class) {
if (instance2 == null) {
instance2 = new SingletonLazy2();
}
}
return instance2;
}
優化同步塊:
當物件已經建立,執行緒再走到 條件(instance2 == null) 為假,當前執行緒還是要等待 之前執行緒釋放鎖,才能去判斷不用建立物件,拜拜浪費時間去等解鎖時間,還不如在鎖外直接判斷就可以跳過這個同步程式碼塊“鎖”。所以優化後:
public static SingletonLazy3 getInstance() {
if (instace3 == null) {
synchronized (SingletonLazy3.class) {
if (instace3 == null) {
instace3 = new SingletonLazy3();
}
}
}
return instace3;
}
還有另外一個想法,單例模式類只建立一個物件,這很符合靜態類的特點,所以該類初始化建立物件寫在靜態塊裡。這已經不是“懶漢式”了。
package demo_singleton;
public class SingletonLazy4 {
private static SingletonLazy4 instance4 = null;
static{
instance4 = new SingletonLazy4();
}
public static SingletonLazy4 getInstance() {
return instance4;
}
private SingletonLazy4() {
}
}
利用靜態內部類,內部類在編譯的時候也是一個單獨的class檔案,在呼叫的時候會執行,不呼叫的時候不會執行。
package demo_singleton;
public class SingletonLazy5 {
private static class Sing {
private static SingletonLazy5 instance = new SingletonLazy5();
}
public static SingletonLazy5 getInstance() {
return Sing.instance;
}
private SingletonLazy5() {
}
}
注意:Java的反射機制也是可以破壞單例的。
2. 工廠模式
工廠模式的定義就是通過工廠建立物件,當用戶需要建立打兩把不同物件的時候,通過定義一個建立物件的介面,讓子類自己決定建立哪一個物件,使用者不再自行判斷例項化哪一個物件不再去關心建立物件的複雜過程。我們通過建立一個工廠類,工廠類的作用就是判斷需要建立拿一個物件,並例項化。
問得好:為什麼不直接new不是更簡單嗎!問得好,這就是為什麼工廠模式出現的意義:需求的變更貫穿於整個專案軟體,設計模式的精髓就在於應對“未來的變化”,主要體現在程式的擴充套件性方面。個人理解:如果我面對的是一個固定的需求,那我用new建立物件沒問題,但是往往我們需要處理的是5❀8?的需求,如果還是死程式,那是沒道理的或者程式碼複雜的一批。工廠模式應運而生,它,實現不同需求建立不同物件。避免隨便亂建立物件,保證程式碼健康。
未完待續,,,