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

建造者模式與原型模式:Java 創建型設計模式深度解析

     編輯:Java 相關知識

建造者模式

核心意圖

將複雜物件的建構過程與其表示分離,使相同建構流程能產生不同表示。適用於:建構步驟固定、但各步驟具體實現多變、物件屬性眾多或有順序依賴。

四大角色

  • Product:最終產品(如 Pizza)
  • Builder:抽象建造者,定義建構步驟介面
  • ConcreteBuilder:具體建造者,實作步驟邏輯
  • Director:指揮者,控制建構順序,隔離客戶端與建造細節

經典實作:客製化披薩


// 產品
class Pizza {
    private String dough, sauce, topping;
    // setter/getter 省略
}

// 抽象建造者
abstract class PizzaBuilder {
    protected Pizza pizza = new Pizza();
    public Pizza getPizza() { return pizza; }
    public void createNewPizza() { pizza = new Pizza(); }
    public abstract void buildDough();
    public abstract void buildSauce();
    public abstract void buildTopping();
}

// 具體建造者:夏威夷披薩
class HawaiianPizzaBuilder extends PizzaBuilder {
    public void buildDough() { pizza.setDough("cross"); }
    public void buildSauce() { pizza.setSauce("mild"); }
    public void buildTopping() { pizza.setTopping("ham+pineapple"); }
}

// 具體建造者:義式辣味披薩
class SpicyPizzaBuilder extends PizzaBuilder {
    public void buildDough() { pizza.setDough("pan baked"); }
    public void buildSauce() { pizza.setSauce("hot"); }
    public void buildTopping() { pizza.setTopping("pepperoni+salami"); }
}

// 指揮者
class Waiter {
    private PizzaBuilder builder;
    public void setBuilder(PizzaBuilder b) { builder = b; }
    public Pizza getPizza() { return builder.getPizza(); }
    public void construct() {
        builder.createNewPizza();
        builder.buildDough();
        builder.buildSauce();
        builder.buildTopping();
    }
}

// 客戶端
public class BuilderDemo {
    public static void main(String[] args) {
        Waiter waiter = new Waiter();
        waiter.setBuilder(new HawaiianPizzaBuilder());
        waiter.construct();
        Pizza pizza = waiter.getPizza(); // 獲得夏威夷披薩
    }
}

現代流暢 API 風格(Lombok @Builder / 手寫鏈式)

public class User {
    private final String name;
    private final int age;
    private final String email;
    private final String phone;

    private User(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
        this.email = builder.email;
        this.phone = builder.phone;
    }

    public static class Builder {
        private String name, email, phone;
        private int age;
        public Builder name(String v) { name = v; return this; }
        public Builder age(int v) { age = v; return this; }
        public Builder email(String v) { email = v; return this; }
        public Builder phone(String v) { phone = v; return this; }
        public User build() { return new User(this); }
    }
}

// 使用
User u = new User.Builder().name("Alice").age(25).email("a@b.com").build();

優點與適用場景

  • 精細控制建構過程,支援多種表示
  • 新增具體建造者即可擴充,符合開閉原則
  • 參數眾多、有預設值、不可變物件建構首選

原型模式

核心意圖

透過複製現有實例建立新實例,而非 new。適用於:建立成本高(大量資料載入、複雜計算)、或需建立相似但非完全相同的物件。

三大角色

  • Prototype:定義 clone() 介面
  • ConcretePrototype:實作複製邏輯
  • Client:呼叫 clone() 獲得新實例

淺複製 vs 深複製


// 淺複製:預設 Object.clone() 行為
class Shallow implements Cloneable {
    int age;
    Person person; // 參考型別
    public Object clone() throws CloneNotSupportedException {
        return super.clone(); // 參考型別共享同一個 Person 物件
    }
}

// 深複製:手動複製參考型別
class Deep implements Cloneable {
    int age;
    Person person;
    public Object clone() throws CloneNotSupportedException {
        Deep d = (Deep) super.clone();
        d.person = new Person(this.person.getName()); // 新建 Person
        return d;
    }
}
// 或實作 Serializable 透過序列化深複製

測試驗證


Shallow s1 = new Shallow(); s1.age=20; s1.person=new Person("Eric");
Shallow s2 = (Shallow) s1.clone();
s1.age = 30; s1.person.setName("Frank");
System.out.println(s2.person.getName()); // Frank → 共享同一 Person

Deep d1 = new Deep(); d1.age=20; d1.person=new Person("Eric");
Deep d2 = (Deep) d1.clone();
d1.age = 30; d1.person.setName("Frank");
System.out.println(d2.person.getName()); // Eric → 獨立 Person

原型管理器(登記式原型)


class PrototypeManager {
    private Map<String, Prototype> prototypes = new HashMap<>();
    public void register(String key, Prototype p) { prototypes.put(key, p); }
    public Prototype get(String key) {
        return prototypes.get(key).clone(); // 取得複製品
    }
}

優點與注意事項

  • 效能優於 new(避免重複初始化邏輯)
  • 隱藏建立細節,客戶端只需知道原型鍵值
  • 淺/深複製選擇關鍵:含可變參考型別必須深複製
  • 實作 Cloneable 並覆寫 clone() 拋出 CloneNotSupportedException 為受檢異常,需處理

兩模式關鍵差異比較

維度建造者模式原型模式
核心手段分步驟組裝複製現有實例
適用物件建構邏輯複雜、參數多、不可變建立成本高、或需大量相似實例
擴充方式新增 ConcreteBuilder新增/註冊 Prototype 實例
狀態管理Director 控制流程原型實例保持狀態快照
典型案例StringBuilder、DocumentBuilder、HttpClient.Builder遊戲實體複製、報表模板複製、原型管理器

結語

建造者模式解決「如何優雅建構複雜物件」,原型模式解決「如何低成本複製現有物件」。實務中常搭配使用:原型作為建造者的預設模板,建造者在複製基礎上進行客製化修改。掌握兩者精髓,能靈活應對各類物件創建挑戰。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved