首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 5 大經典創建型設計模式深度解析與代碼實戰

     編輯:Java 相關知識

前言

設計模式是軟件工程的基石。創建型模式關注對象的實例化過程,將創建邏輯與使用邏輯解耦,提高系統的靈活性與可維護性。本文深度解析 **工廠方法、抽象工廠、單例、建造者、原型** 五大創建型模式,提供標準 UML 結構說明、完整可運行 Java 代碼、核心優缺點對比及實戰應用場景。

一、設計模式六大原則(速查)

原則核心含義指導意義
開閉原則 (OCP)對擴展開放,對修改關閉熱插拔,通過接口/抽象擴展而不改動核心代碼
里氏替換 (LSP)子類必須能替換父類繼承需謹慎,優先組合;參數卻變、返回協變、異常收窄
依賴倒置 (DIP)依賴抽象不依賴具體面向接口編程,高層模塊不依賴低層模塊
接口隔離 (ISP)多個專用接口優於單一總接口降低耦合,避免「胖接口」強制實現無用方法
迪米特法則 (LoD)最少知識原則只與直接朋友通信,減少對象間耦合
合成復用 (CRP)優先組合/聚合,少用繼承保持封裝性,靈活復用

二、五大創建型模式詳細解析

1. 工廠方法模式

定義:定義一個創建對象的接口,由子類決定實例化哪個類。包含三種變體:

1.1 簡單工廠(非標準模式,但極常用)

// 產品接口
interface Product { void use(); }
// 具體產品
class ConcreteProductA implements Product { public void use() { System.out.println("產品A"); } }
class ConcreteProductB implements Product { public void use() { System.out.println("產品B"); } }
// 工廠類
class SimpleFactory {
    public Product create(String type) {
        switch (type) {
            case "A": return new ConcreteProductA();
            case "B": return new ConcreteProductB();
            default: throw new IllegalArgumentException("未知類型");
        }
    }
}
// 客戶端
Product p = new SimpleFactory().create("A"); p.use();

缺點:違反 OCP,添加產品需修改工廠類。

1.2 工廠方法(標準模式)

將創建邏輯延遲到子類,每個產品對應一個工廠子類。


abstract class Factory {
    public abstract Product create(); // 工廠方法
}
class FactoryA extends Factory { public Product create() { return new ConcreteProductA(); } }
class FactoryB extends Factory { public Product create() { return new ConcreteProductB(); } }

// 客戶端只依賴抽象工廠
Factory factory = new FactoryA(); // 或從配置/注入獲取
Product product = factory.create();

優點:符合 OCP,新增產品只需新增工廠子類,不修改現有代碼。

1.3 靜態工廠方法

工廠方法聲明為 static,無需實例化工廠。如 Collections.singletonList()、Boolean.valueOf()。

2. 抽象工廠模式

定義:提供一個接口,用於創建**相關或依賴對象的家族**,而不指定具體類。解決「產品族」一致性問題。

場景:皮膚主題(按鈕+輸入框+窗口)、跨平台 GUI、多数據庫適配(Connection+Statement+ResultSet)。


// 抽象產品族
interface Button { void render(); }
interface Checkbox { void render(); }

// 具體產品族 Win/Mac
class WinButton implements Button { public void render() { System.out.println("Win按鈕"); } }
class WinCheckbox implements Checkbox { public void render() { System.out.println("Win複選框"); } }
class MacButton implements Button { /* ... */ }
class MacCheckbox implements Checkbox { /* ... */ }

// 抽象工廠
interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

// 具體工廠
class WinFactory implements GUIFactory {
    public Button createButton() { return new WinButton(); }
    public Checkbox createCheckbox() { return new WinCheckbox(); }
}
class MacFactory implements GUIFactory { /* ... */ }

// 客戶端
GUIFactory factory = new WinFactory(); // 運行時決定
Button btn = factory.createButton();
Checkbox cb = factory.createCheckbox();
// 保證 btn 和 cb 風格一致

3. 單例模式

定義:保證一個類僅有一個實例,並提供全局訪問點。

3.1 懶漢式(線程不安全)


public class Singleton {
    private static Singleton instance;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) instance = new Singleton();
        return instance;
    }
}

3.2 雙重檢查鎖 (DCL) - 推薦高性能線程安全


public class Singleton {
    private static volatile Singleton instance; // volatile 禁止指令重排
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) instance = new Singleton();
            }
        }
        return instance;
    }
}

3.3 靜態內部類(推薦:線程安全、延遲加載、代碼簡潔)


public class Singleton {
    private Singleton() {}
    private static class Holder { static final Singleton INSTANCE = new Singleton(); }
    public static Singleton getInstance() { return Holder.INSTANCE; }
}

3.4 枚舉單例(最推薦:天然線程安全、防反射/序列化破壞)


public enum Singleton { INSTANCE; public void doSomething() {} }
// 調用:Singleton.INSTANCE.doSomething();

4. 建造者模式

定義:將複雜對象的構建與表示分離,使相同構建過程可創建不同表示。適用於:構造器參數超過 4 個、參數有默認值、需要不可變對象。

角色:Product(產品)、Builder(抽象建造者)、ConcreteBuilder(具體建造者)、Director(指揮者)。


// 產品
class Person {
    private String head, body, foot;
    // getter/setter...
    @Override public String toString() { return "Person{head=" + head + ", body=" + body + ", foot=" + foot + "}"; }
}

// 抽象建造者
interface PersonBuilder {
    void buildHead();
    void buildBody();
    void buildFoot();
    Person build();
}

// 具體建造者
class ManBuilder implements PersonBuilder {
    private Person person = new Person();
    public void buildHead() { person.setHead("男人頭"); }
    public void buildBody() { person.setBody("男人身體"); }
    public void buildFoot() { person.setFoot("男人腳"); }
    public Person build() { return person; }
}
class WomanBuilder implements PersonBuilder { /* ... */ }

// 指揮者:控制構建順序
class PersonDirector {
    public Person construct(PersonBuilder builder) {
        builder.buildHead();
        builder.buildBody();
        builder.buildFoot();
        return builder.build();
    }
}

// 客戶端
PersonDirector director = new PersonDirector();
Person man = director.construct(new ManBuilder());
Person woman = director.construct(new WomanBuilder());

現代變體:鏈式調用 Builder(如 Lombok @Builder、StringBuilder、HttpClientBuilder),省去 Director,直接鏈式設置屬性最後 .build()。

5. 原型模式

定義:通過複製現有實例(原型)創建新對象,而非通過構造器。核心在於 clone() 實現淺拷貝與深拷貝的區別。

5.1 淺拷貝 vs 深拷貝

類型基本類型引用類型實現方式
淺拷貝重新創建(值傳遞)複製引用(指向同一對象)super.clone() 默認實現
深拷貝重新創建遞歸創建新對象序列化/反序列化、手動 new、拷貝構造器

5.2 代碼實現


class Prototype implements Cloneable, Serializable {
    private int primitiveField;
    private MutableObject referenceField; // 可變引用對象

    // 淺拷貝
    @Override protected Prototype clone() throws CloneNotSupportedException {
        return (Prototype) super.clone();
    }

    // 深拷貝:序列化+反序列化(通用但有性能開銷)
    public Prototype deepClone() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (Prototype) ois.readObject();
    }
}

// 測試
Prototype p1 = new Prototype(); p1.setPrimitiveField(1); p1.setReferenceField(new MutableObject(2));
Prototype p2 = p1.clone();       // 淺拷貝:p2.referenceField == p1.referenceField 為 true
Prototype p3 = p1.deepClone();   // 深拷貝:p3.referenceField != p1.referenceField 為 true

三、模式選型決策表

場景推薦模式關鍵判斷依據
單一產品、創建邏輯固定、客戶端不關心細節簡單工廠不需擴展、代碼集中
產品族固定、需支持多平台/主題、保證族內一致性抽象工廠「一組相關對象」而非單個
全局唯一實例、狀態共享、延遲加載單例(枚舉/靜態內部類)線程安全、防破壞
構造參數多、可選參數多、需不可變對象、構建步驟固定建造者鏈式調用、Director 控制順序
創建成本高、對象狀態相似、需動態增減原型原型clone()、深/淺拷貝選擇

四、總結

  • 工廠方法解耦創建邏輯,抽象工廠解決產品族一致性。
  • 單例首選 枚舉 或 靜態內部類,拒絕雙重檢查鎖(除非極度在意性能微調)。
  • 建造者是構造器參數過多的最佳替代方案,現代多用鏈式 API。
  • 原型核心在於深拷貝實現,序列化法通用但慢,手動拷貝快但繁瑣,按需選擇。
  • 所有模式最終服務於 **OCP** 與 **DIP**:將變化點封裝,面向抽象編程。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved