1. 程式人生 > 實用技巧 >java設計模式總結(二) ---- 五中建立型模式(引用一下韓老師的程式碼)

java設計模式總結(二) ---- 五中建立型模式(引用一下韓老師的程式碼)

設計模式的分類

總體來說設計模式分為三大類:

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

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

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

https://www.cnblogs.com/fswhq/p/sjms.html

建立模式(5種)

工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式

1,單例設計模式

定義:確保一個類最多隻有一個例項,並提供一個全域性訪問點

八種方式:

1> 餓漢式(靜態常量)

2> 餓漢式(靜態程式碼塊)

3> 懶漢式(執行緒不安全)

4> 懶漢式(同步方法)

5> 懶漢式(同步程式碼塊)

6> 雙重檢查

7> 靜態內部類

8> 列舉

1.1餓漢式(靜態常量)

class Singleton {
    
    //1. 構造器私有化, 外部能new
    private Singleton() {
        
    }
    
    //2.本類內部建立物件例項
    private final static Singleton instance = new Singleton();
    
    
//3. 提供一個公有的靜態方法,返回例項物件 public static Singleton getInstance() { return instance; } }

優點:簡單,沒有執行緒安全問題

缺點:老友Lazy Loading效果,沒有使用該單例時,浪費記憶體

1.2餓漢式(靜態程式碼塊)

class Singleton {
    
    //1. 構造器私有化, 外部能new
    private Singleton() {
        
    }
    

    //2.本類內部建立物件例項
    private  static
Singleton instance; static { // 在靜態程式碼塊中,建立單例物件 instance = new Singleton(); } //3. 提供一個公有的靜態方法,返回例項物件 public static Singleton getInstance() { return instance; } }

優缺點和上面一種餓漢式差不多

1.3懶漢式(執行緒不安全)

class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    //提供一個靜態的公有方法,當使用到該方法時,才去建立 instance
    //即懶漢式
    public static Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

優缺點:

有Lazy Loading的效果,只能在單執行緒下使用

多執行緒下會出現多個例項

不要使用這種方式

class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    //提供一個靜態的公有方法,加入同步處理的程式碼,解決執行緒安全問題
    //即懶漢式
    public static synchronized Singleton getInstance() {
        if(instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

優缺點:沒有執行緒安全問題

效率太低,每次都要進去都要同步

1.5懶漢式(執行緒安全,同步程式碼塊)

// 懶漢式(執行緒安全,同步方法)
class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    //提供一個靜態的公有方法,加入同步處理的程式碼,解決執行緒安全問題
    //即懶漢式
    public static  Singleton getInstance() {
        if(instance == null) {
            synchronized(Singleton.class){

                instance = new Singleton();
            }
        }
        return instance;
    }
}

多執行緒時會產生多例

1.6 雙重檢查

class Singleton {
    private static volatile Singleton instance;
    
    private Singleton() {}
    
    //提供一個靜態的公有方法,加入雙重檢查程式碼,解決執行緒安全問題, 同時解決懶載入問題
    //同時保證了效率, 推薦使用
    
    public static synchronized Singleton getInstance() {
        if(instance == null) {
            synchronized (Singleton.class) {
                if(instance == null) {
                    instance = new Singleton();
                }
            }
            
        }
        return instance;
    }
}

優缺點:執行緒安全;延遲載入;效率高

1.7 靜態內部類

// 靜態內部類完成, 推薦使用
class Singleton {
    private static volatile Singleton instance;
    
    //構造器私有化
    private Singleton() {}
    
    //寫一個靜態內部類,該類中有一個靜態屬性 Singleton
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton(); 
    }
    
    //提供一個靜態的公有方法,直接返回SingletonInstance.INSTANCE
    
    public static synchronized Singleton getInstance() {
        
        return SingletonInstance.INSTANCE;
    }
}

優缺點:使用類載入機制;使用時在例項化;第一次載入時才初始化jvm保證單例

1.8 列舉

//使用列舉,可以實現單例, 推薦
enum Singleton {
    INSTANCE; //屬性
}

JDK5.0新特性,還防止了序列化

1.9單例模式在JDK中的使用

使用的餓漢式

1.10細節說明和使用事項

                        

1 工廠模式(包括簡單工廠,工廠方法,抽象工廠)

1.1 簡單工廠模式

定義:定義了一個建立物件的類,由這個類來封裝例項化物件的行為。

舉例:(我們舉一個pizza工廠的例子)

使用簡單工廠:

public Pizza createPizza(String orderType) {

        Pizza pizza = null;

        System.out.println("使用簡單工廠模式");
        if (orderType.equals("greek")) {
            pizza = new GreekPizza();
            pizza.setName(" 希臘披薩 ");
        } else if (orderType.equals("cheese")) {
            pizza = new CheesePizza();
            pizza.setName(" 乳酪披薩 ");
        } else if (orderType.equals("pepper")) {
            pizza = new PepperPizza();
            pizza.setName("胡椒披薩");
        }
        
        return pizza;
    }

1.2 工廠方法模式

定義:定義了一個建立物件的抽象方法,由子類決定要例項化的類。工廠方法模式將物件的例項化推遲到子類。

舉例:(我們依然舉pizza工廠的例子,不過這個例子中,pizza產地有兩個:倫敦和紐約)。添加了一個新的產地,如果用簡單工廠模式的的話,我們要去修改工廠程式碼,並且會增加一堆的if else語句。而工廠方法模式克服了簡單工廠要修改程式碼的缺點,它會直接建立兩個工廠,紐約工廠和倫敦工廠。類圖如下:

在簡單工廠的基礎上增加了多個工廠,就讓一個父類工廠去管理

子類的主要程式碼和簡答工廠差不多

public class BJOrderPizza extends OrderPizza {

    
    @Override
    Pizza createPizza(String orderType) {
    
        Pizza pizza = null;
        if(orderType.equals("cheese")) {
            pizza = new BJCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new BJPepperPizza();
        }
        // TODO Auto-generated method stub
        return pizza;
    }

}

1.3 抽象工廠模式

定義:定義了一個介面用於建立相關或有依賴關係的物件族,而無需明確指定具體類。

舉例:(我們依然舉pizza工廠的例子,pizza工廠有兩個:紐約工廠和倫敦工廠)。類圖如下:

//一個抽象工廠模式的抽象層(介面)
public interface AbsFactory {
    //讓下面的工廠子類來 具體實現
    public Pizza createPizza(String orderType);
}

把工廠方法模式加到介面之中,區別感覺不大

1.4工廠在JDK中的使用

  在Calader中使用了簡單工廠模式,根據時區來建立相應的子類物件

總結:工廠的好處,在建立的物件的時候我們會有各種各樣的要求,我們把這一部分都講給工廠去處理。我們在使用的時候只需要用方法區獲取到類就行。不程式碼分離開

    簡單工廠:根據條件new

    工廠方法:用父類來管理相似的工廠類

    抽象工廠模式:用介面來管理相關的工廠類

ps:該模式是違反ocp原則的,對於新類工廠無法進行擴充套件。因為要去改工廠原本的方法

3原型模式

原型模式就是對一個類進行復制,在Cloneable介面中已經實現了,我們重寫一下就行

@Override
    protected Object clone()  {
        
        Sheep sheep = null;
        try {
            sheep = (Sheep)super.clone();
        } catch (Exception e) {
            // TODO: handle exception
            System.out.println(e.getMessage());
        }
        // TODO Auto-generated method stub
        return sheep;
    }

深拷貝和淺拷貝:如果我們在clone方法中,拷貝對於類中以其他類作為屬性時,我們把他指向同一個物件,這樣複製出來的過程叫淺拷貝,否則,就是深拷貝。如下圖

淺拷貝:

我們的類屬性:

重寫clone:

客戶端複製:

執行結果:

上圖就是淺拷貝。

下面是深拷貝,有兩種方式,方式一在複製屬性物件時我們把該物件裡面的clone也重新並且呼叫:

public String name; //String 屬性
    public DeepCloneableTarget deepCloneableTarget;// 引用型別
    public DeepProtoType() {
        super();
    }
    
    
    //深拷貝 - 方式 1 使用clone 方法
    @Override
    protected Object clone() throws CloneNotSupportedException {
        
        Object deep = null;
        //這裡完成對基本資料型別(屬性)和String的克隆
        deep = super.clone(); 
        //對引用型別的屬性,進行單獨處理
        DeepProtoType deepProtoType = (DeepProtoType)deep;
        deepProtoType.deepCloneableTarget  = (DeepCloneableTarget)deepCloneableTarget.clone();
        
        // TODO Auto-generated method stub
        return deepProtoType;
    }

方式二,進行序列化,再進行反序列化:

public String name; //String 屬性
    public DeepCloneableTarget deepCloneableTarget;// 引用型別
    public DeepProtoType() {
        super();
    }
public Object deepClone() {
        
        //建立流物件
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        
        try {
            
            //序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this); //當前這個物件以物件流的方式輸出
            
            //反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            DeepProtoType copyObj = (DeepProtoType)ois.readObject();
            
            return copyObj;
            
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            return null;
        } finally {
            //關閉流
            try {
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
                // TODO: handle exception
                System.out.println(e2.getMessage());
            }
        }
        
    }

原型設計模式在Spring bean設定當中使用了

以上就是原型模式的全部內容。

4 建造者模式(生成器模式)

作用:把一個複雜的物件,內部結構和操作分離開來。內部結構不呈現給使用者

以造房子為例,傳統方式

畫紅線處,操作在使用者用體現。

使用建造者模式:

指揮者去完成功能

在JDK--StringBuilder中的應用

好了,五中建立型模式就寫到這兒,我寫的東西不會放全部程式碼,會多給原理圖和重要程式碼截圖