🎭 創建型設計模式:對象誕生的藝術與智慧
💡 溫馨提示:本文將以輕松有趣的方式帶你探索設計模式的世界,就像在聽一個關于"如何優雅地生孩子"的故事一樣!
🚪 傳送門:在開始我們的"對象制造之旅"之前,建議先通過這個 🎨 Java設計模式詳解:讓代碼優雅如詩的秘密武器 了解設計模式的基礎概念和整體架構,這樣能讓你更好地理解本文內容!就像玩游戲要先看新手教程一樣!🎮
🏗? 創建型設計模式整體架構
🎪 引言:為什么我們需要設計模式?
🏭 場景:混亂的代碼工廠 🏭
┌─────────────────────────────────────┐
│ 💻 程序員小王的一天 💻 │
│ │
│ 😵 "new"操作符滿天飛! │
│ 🔥 代碼重復像復制粘貼大賽! │
│ 🐛 Bug多得像夏天的蚊子! │
│ │
│ 💡 突然,設計模式英雄出現了! │
│ 🦸?♂? "讓我來拯救你的代碼!" │
└─────────────────────────────────────┘
創建型設計模式就像是"對象制造"的標準作業流程,讓代碼變得優雅、可維護、可擴展。
本文將帶你探索五種創建型設計模式,就像參觀五個不同的"對象制造車間"一樣有趣!
🎯 本文你將學到什么?
🎬 設計模式英雄聯盟 🎬
┌─────────────────────────────────────┐
│ 🦸?♂? 五位設計模式英雄登場! │
│ │
│ 🎭 單例俠:確保全局唯一 │
│ 🏭 工廠俠:讓子類決定創建什么 │
│ 🏭 抽象工廠俠:創建系列相關產品 │
│ 🏭 建造者俠:分步驟構建復雜對象 │
│ 🏭 原型俠:克隆現有對象 │
│ │
│ 🚀 準備好開始冒險了嗎? │
└─────────────────────────────────────┘
🏭 第一部分:單例模式(Singleton Pattern)
🎭 單例俠的登場 🎭
┌─────────────────────────────────────┐
│ 👑 單例俠:我是唯一的存在! │
│ │
│ 🏢 公司CEO:"我要一個總經理!" │
│ 👔 單例俠:"只能有一個!" │
│ 🏢 公司CEO:"再來一個!" │
│ 👔 單例俠:"還是同一個!" │
│ │
│ 💡 核心思想:確保全局唯一 │
└─────────────────────────────────────┘
🏗? 單例模式UML類圖
?? 單例模式時序圖
1.1 🎭 什么是單例模式?
一句話理解:確保一個類只有一個實例,就像公司只有一個總經理!
定義:確保一個類只有一個實例,并提供一個全局訪問點。
應用場景:數據庫連接池、配置管理器、日志記錄器、緩存管理器
1.2 🛠? 單例模式的實現方式
實現方式 | 特點 | 推薦度 |
---|---|---|
餓漢式 | 線程安全,但可能浪費內存 | ??? |
懶漢式 | 延遲加載,但線程不安全 | ?? |
雙重檢查鎖定 | 延遲加載 + 線程安全 | ???? |
枚舉單例 | 自動線程安全,最優雅 | ????? |
1.2.1 🍔 餓漢式單例(Eager Singleton)
💡 小貼士:就像你提前準備好午餐一樣,餓漢式在類加載時就創建了實例,所以叫"餓漢"(迫不及待)!
特點:線程安全,但可能造成不必要的內存占用
public class EagerSingleton {private static final EagerSingleton INSTANCE = new EagerSingleton();private EagerSingleton() {}public static EagerSingleton getInstance() {return INSTANCE;}
}
1.2.2 😴 懶漢式單例(Lazy Singleton)
💡 小貼士:就像你等到餓了才去做飯一樣,懶漢式只有在第一次使用時才創建實例,所以叫"懶漢"(能拖就拖)!
特點:延遲加載,但需要處理線程安全問題
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {}public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}
1.2.3 🔒 雙重檢查鎖定單例(Double-Checked Locking)
💡 小貼士:這是懶漢式的升級版!就像你進房間前先敲門,確認沒人再進去,然后再鎖門一樣,雙重檢查確保線程安全!
特點:延遲加載 + 線程安全,性能最優
public class DoubleCheckedSingleton {private static volatile DoubleCheckedSingleton instance;private DoubleCheckedSingleton() {}public static DoubleCheckedSingleton getInstance() {if (instance == null) {synchronized (DoubleCheckedSingleton.class) {if (instance == null) {instance = new DoubleCheckedSingleton();}}}return instance;}
}
1.2.4 🎯 枚舉單例(Enum Singleton)
💡 小貼士:這是Java中最優雅的單例實現方式!就像枚舉天生就是單例一樣,簡單、安全、優雅!
特點:自動線程安全,自動序列化安全,推薦使用
public enum EnumSingleton {INSTANCE;public void doSomething() {System.out.println("枚舉單例執行操作");}
}
📊 單例模式實現方式對比表
1.3 🎯 單例模式的實際應用
// 配置管理器單例
public class ConfigManager {private static final ConfigManager INSTANCE = new ConfigManager();private final Properties properties;private ConfigManager() {properties = new Properties();loadConfig();}public static ConfigManager getInstance() {return INSTANCE;}private void loadConfig() {// 加載配置文件}public String getProperty(String key) {return properties.getProperty(key);}
}
🏭 第二部分:工廠方法模式(Factory Method Pattern)
🏭 工廠俠的登場 🏭
┌─────────────────────────────────────┐
│ 🏭 工廠俠:我有多個車間! │
│ │
│ 🚗 轎車車間:"我要生產轎車!" │
│ 🚐 面包車車間:"我要生產面包車!" │
│ 🚚 卡車車間:"我要生產卡車!" │
│ │
│ 🏭 工廠俠:"每個車間都有自己的 │
│ 制造方法,但都遵循同一協議!" │
└─────────────────────────────────────┘
🏗? 工廠方法模式UML類圖
?? 工廠方法模式時序圖
2.1 🏭 什么是工廠方法模式?
一句話理解:讓子類決定創建什么對象,就像不同車間生產不同產品!
定義:定義一個用于創建對象的接口,讓子類決定實例化哪一個類。
應用場景:數據庫連接器創建、日志記錄器創建、文件處理器創建
2.2 🛠? 工廠方法模式的實現
// 抽象產品
public interface Product {void operation();
}// 具體產品
public class ConcreteProductA implements Product {@Overridepublic void operation() {System.out.println("具體產品A的操作");}
}// 抽象工廠
public interface Factory {Product createProduct();
}// 具體工廠
public class ConcreteFactoryA implements Factory {@Overridepublic Product createProduct() {return new ConcreteProductA();}
}
2.3 🗄? 數據庫連接器工廠示例
// 數據庫連接器接口
public interface DatabaseConnector {void connect();void disconnect();void executeQuery(String sql);
}// MySQL連接器
public class MySQLConnector implements DatabaseConnector {@Overridepublic void connect() {System.out.println("連接到MySQL數據庫");}@Overridepublic void disconnect() {System.out.println("斷開MySQL數據庫連接");}@Overridepublic void executeQuery(String sql) {System.out.println("在MySQL中執行查詢: " + sql);}
}// 數據庫連接器工廠接口
public interface DatabaseConnectorFactory {DatabaseConnector createConnector();
}// MySQL連接器工廠
public class MySQLConnectorFactory implements DatabaseConnectorFactory {@Overridepublic DatabaseConnector createConnector() {return new MySQLConnector();}
}
🏭 第三部分:抽象工廠模式(Abstract Factory Pattern)
🏭 抽象工廠俠的登場 🏭
┌─────────────────────────────────────┐
│ 🏭 抽象工廠俠:我提供完整生態! │
│ │
│ 📱 蘋果工廠:"iPhone + AirPods + │
│ 蘋果充電器,完美搭配!" │
│ 📱 三星工廠:"Galaxy + Galaxy Buds │
│ + 三星充電器,系列相關!" │
│ │
│ 🏭 抽象工廠俠:"確保產品兼容性!" │
└─────────────────────────────────────┘
🏗? 抽象工廠模式UML類圖
🏭 抽象工廠模式產品族結構
3.1 🏭 什么是抽象工廠模式?
一句話理解:創建一系列相關產品,就像品牌提供完整生態!
定義:提供一個創建一系列相關或相互依賴對象的接口,而無需指定它們的具體類。
應用場景:UI組件庫、數據庫訪問層、操作系統適配、主題系統
3.2 🛠? 抽象工廠模式的實現
// 抽象產品A
public interface AbstractProductA {void operationA();
}// 抽象產品B
public interface AbstractProductB {void operationB();
}// 具體產品A1
public class ConcreteProductA1 implements AbstractProductA {@Overridepublic void operationA() {System.out.println("具體產品A1的操作");}
}// 抽象工廠
public interface AbstractFactory {AbstractProductA createProductA();AbstractProductB createProductB();
}// 具體工廠1
public class ConcreteFactory1 implements AbstractFactory {@Overridepublic AbstractProductA createProductA() {return new ConcreteProductA1();}@Overridepublic AbstractProductB createProductB() {return new ConcreteProductB1();}
}
3.3 🖥? UI組件工廠示例
// UI組件接口
public interface Button {void render();void onClick();
}public interface Checkbox {void render();void check();
}// Windows風格組件
public class WindowsButton implements Button {@Overridepublic void render() {System.out.println("渲染Windows風格按鈕");}@Overridepublic void onClick() {System.out.println("Windows按鈕點擊事件");}
}// UI工廠接口
public interface UIFactory {Button createButton();Checkbox createCheckbox();
}// Windows UI工廠
public class WindowsUIFactory implements UIFactory {@Overridepublic Button createButton() {return new WindowsButton();}@Overridepublic Checkbox createCheckbox() {return new WindowsCheckbox();}
}
🏭 第四部分:建造者模式(Builder Pattern)
🏭 建造者俠的登場 🏭
┌─────────────────────────────────────┐
│ 🏭 建造者俠:我一步步組裝! │
│ │
│ 🎨 步驟1:"選擇車身顏色!" │
│ 🚗 步驟2:"選擇發動機型號!" │
│ 🎵 步驟3:"選擇音響系統!" │
│ 🪑 步驟4:"選擇座椅材質!" │
│ │
│ 🏭 建造者俠:"最終組裝成獨一無二 │
│ 的汽車!" │
└─────────────────────────────────────┘
🏗? 建造者模式UML類圖
🔄 建造者模式構建流程圖
?? 建造者模式時序圖
4.1 🏗? 什么是建造者模式?
一句話理解:分步驟構建復雜對象,就像定制汽車一步步組裝!
定義:將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
應用場景:復雜對象的創建、參數較多的構造函數、鏈式調用
4.2 🛠? 建造者模式的實現
// 產品類
public class Computer {private String cpu;private String memory;private String storage;private String graphicsCard;private String motherboard;// Getters and Setterspublic String getCpu() { return cpu; }public void setCpu(String cpu) { this.cpu = cpu; }public String getMemory() { return memory; }public void setMemory(String memory) { this.memory = memory; }// ... 其他getter和setter@Overridepublic String toString() {return "Computer{" +"cpu='" + cpu + '\'' +", memory='" + memory + '\'' +", storage='" + storage + '\'' +", graphicsCard='" + graphicsCard + '\'' +", motherboard='" + motherboard + '\'' +'}';}
}// 抽象建造者
public abstract class ComputerBuilder {protected Computer computer = new Computer();public abstract void buildCpu();public abstract void buildMemory();public abstract void buildStorage();public abstract void buildGraphicsCard();public abstract void buildMotherboard();public Computer getResult() {return computer;}
}// 具體建造者 - 游戲電腦
public class GamingComputerBuilder extends ComputerBuilder {@Overridepublic void buildCpu() {computer.setCpu("Intel i9-12900K");}@Overridepublic void buildMemory() {computer.setMemory("32GB DDR5");}@Overridepublic void buildStorage() {computer.setStorage("2TB NVMe SSD");}@Overridepublic void buildGraphicsCard() {computer.setGraphicsCard("RTX 4090");}@Overridepublic void buildMotherboard() {computer.setMotherboard("Z690 Gaming");}
}// 導演類
public class ComputerDirector {private ComputerBuilder builder;public void setBuilder(ComputerBuilder builder) {this.builder = builder;}public Computer construct() {builder.buildCpu();builder.buildMemory();builder.buildStorage();builder.buildGraphicsCard();builder.buildMotherboard();return builder.getResult();}
}
4.3 🔗 鏈式建造者(Fluent Builder)
// 鏈式建造者
public class Computer {private String cpu;private String memory;private String storage;private String graphicsCard;private String motherboard;private Computer() {}public static ComputerBuilder builder() {return new ComputerBuilder();}// 內部建造者類public static class ComputerBuilder {private Computer computer = new Computer();public ComputerBuilder cpu(String cpu) {computer.cpu = cpu;return this;}public ComputerBuilder memory(String memory) {computer.memory = memory;return this;}public ComputerBuilder storage(String storage) {computer.storage = storage;return this;}public ComputerBuilder graphicsCard(String graphicsCard) {computer.graphicsCard = graphicsCard;return this;}public ComputerBuilder motherboard(String motherboard) {computer.motherboard = motherboard;return this;}public Computer build() {// 驗證必填字段if (computer.cpu == null) {throw new IllegalArgumentException("CPU是必填項");}if (computer.memory == null) {throw new IllegalArgumentException("內存是必填項");}return computer;}}
}// 使用示例
public class ChainBuilderDemo {public static void main(String[] args) {Computer computer = Computer.builder().cpu("Intel i7-12700K").memory("32GB DDR4").storage("1TB NVMe SSD").graphicsCard("RTX 3080").motherboard("Z690").build();System.out.println("鏈式構建的電腦: " + computer);}
}
🏭 第五部分:原型模式(Prototype Pattern)
🏭 原型俠的登場 🏭
┌─────────────────────────────────────┐
│ 🏭 原型俠:我會克隆! │
│ │
│ 🧬 科學家:"我要復制這個細胞!" │
│ 🏭 原型俠:"克隆成功!" │
│ 🧬 科學家:"我要創建新變種!" │
│ 🏭 原型俠:"基于原型創建!" │
│ │
│ 🏭 原型俠:"避免重新培養的復雜 │
│ 過程!" │
└─────────────────────────────────────┘
🏗? 原型模式UML類圖
🧬 原型模式克隆流程圖
5.1 🧬 什么是原型模式?
一句話理解:克隆現有對象創建新對象,就像生物克隆一樣神奇!
定義:用原型實例指定創建對象的種類,并且通過復制這些原型創建新的對象。
應用場景:對象創建成本較高、避免構造函數的約束、動態加載類
5.2 🛠? 原型模式的實現
// 原型接口
public interface Prototype extends Cloneable {Prototype clone();
}// 具體原型
public class ConcretePrototype implements Prototype {private String name;private int age;private List<String> hobbies;public ConcretePrototype(String name, int age, List<String> hobbies) {this.name = name;this.age = age;this.hobbies = new ArrayList<>(hobbies);}@Overridepublic Prototype clone() {try {ConcretePrototype cloned = (ConcretePrototype) super.clone();// 深拷貝hobbies列表cloned.hobbies = new ArrayList<>(this.hobbies);return cloned;} catch (CloneNotSupportedException e) {throw new RuntimeException("克隆失敗", e);}}// Getters and Setterspublic String getName() { return name; }public void setName(String name) { this.name = name; }public int getAge() { return age; }public void setAge(int age) { this.age = age; }public List<String> getHobbies() { return hobbies; }public void setHobbies(List<String> hobbies) { this.hobbies = hobbies; }@Overridepublic String toString() {return "ConcretePrototype{" +"name='" + name + '\'' +", age=" + age +", hobbies=" + hobbies +'}';}
}
5.3 📄 文檔模板系統示例
// 文檔接口
public interface Document extends Cloneable {Document clone();void setContent(String content);void setAuthor(String author);void setDate(String date);void display();
}// 報告文檔
public class Report implements Document {private String title;private String content;private String author;private String date;private List<String> sections;public Report(String title) {this.title = title;this.sections = new ArrayList<>();}@Overridepublic Document clone() {try {Report cloned = (Report) super.clone();// 深拷貝sections列表cloned.sections = new ArrayList<>(this.sections);return cloned;} catch (CloneNotSupportedException e) {throw new RuntimeException("克隆失敗", e);}}@Overridepublic void setContent(String content) {this.content = content;}@Overridepublic void setAuthor(String author) {this.author = author;}@Overridepublic void setDate(String date) {this.date = date;}public void addSection(String section) {sections.add(section);}@Overridepublic void display() {System.out.println("報告標題: " + title);System.out.println("作者: " + author);System.out.println("日期: " + date);System.out.println("內容: " + content);System.out.println("章節: " + sections);}
}// 文檔管理器
public class DocumentManager {private Map<String, Document> prototypes = new HashMap<>();public void addPrototype(String key, Document document) {prototypes.put(key, document);}public Document getClone(String key) {Document prototype = prototypes.get(key);if (prototype == null) {throw new IllegalArgumentException("原型不存在: " + key);}return prototype.clone();}
}
5.4 🔍 深拷貝與淺拷貝
拷貝類型 | 特點 | 適用場景 |
---|---|---|
淺拷貝 | 只復制對象引用,不復制引用對象 | 簡單對象,無嵌套引用 |
深拷貝 | 復制對象及其所有引用對象 | 復雜對象,有嵌套引用 |
關鍵點:原型模式中通常需要深拷貝來避免對象間的相互影響。
// 淺拷貝示例
public class ShallowCopyExample {public static void main(String[] args) {List<String> originalList = Arrays.asList("Java", "Python", "C++");ConcretePrototype original = new ConcretePrototype("張三", 25, originalList);ConcretePrototype cloned = (ConcretePrototype) original.clone();// 修改原始對象的hobbiesoriginal.getHobbies().add("JavaScript");System.out.println("原始對象: " + original);System.out.println("克隆對象: " + cloned);// 注意:淺拷貝時,克隆對象的hobbies也會被修改}
}// 深拷貝實現
public class DeepCopyExample {public static void main(String[] args) {List<String> originalList = Arrays.asList("Java", "Python", "C++");ConcretePrototype original = new ConcretePrototype("張三", 25, originalList);ConcretePrototype cloned = (ConcretePrototype) original.clone();// 修改原始對象的hobbiesoriginal.getHobbies().add("JavaScript");System.out.println("原始對象: " + original);System.out.println("克隆對象: " + cloned);// 深拷貝時,克隆對象的hobbies不會被修改}
}
🎉 總結:創建型設計模式大揭秘
🎬 設計模式英雄聯盟大結局 🎬
┌─────────────────────────────────────┐
│ 🎊 恭喜你完成學習之旅! │
│ │
│ 🎭 單例俠:"我是唯一的存在!" │
│ 🏭 工廠俠:"我讓子類選擇!" │
│ 🏭 抽象工廠俠:"我創建系列產品!" │
│ 🏭 建造者俠:"我一步步組裝!" │
│ 🏭 原型俠:"我會克隆!" │
│ │
│ 🦸?♂? 五位英雄聯手,代碼更優雅! │
└─────────────────────────────────────┘
🏆 創建型設計模式對比表
🎯 設計模式選擇流程圖
🧠 創建型設計模式思維導圖
🎯 選擇建議(簡單記憶法):
- 🎭 單例模式:當你需要"唯一"時
- 🏭 工廠方法模式:當你需要"選擇"時
- 🏭 抽象工廠模式:當你需要"系列"時
- 🏭 建造者模式:當你需要"組裝"時
- 🏭 原型模式:當你需要"復制"時
🏗? 實際應用場景架構圖
💡 實踐要點:
- 🎯 理解場景:根據具體業務場景選擇合適的設計模式
- 🚫 避免過度設計:不是所有地方都需要使用設計模式(不要為了用而用)
- ? 考慮性能:設計模式可能帶來一定的性能開銷
- ? 保持簡單:優先選擇簡單的解決方案(KISS原則)
🎊 恭喜你!
通過這次學習,你已經掌握了創建型設計模式的核心思想!現在你可以在實際項目中:
- 🎯 更好地管理對象的創建過程
- 🚀 提高代碼的可維護性和可擴展性
- 💪 寫出更優雅、更專業的代碼
記住:設計模式不是銀彈,而是工具箱中的工具。選擇合適的設計模式,讓你的代碼更加優雅!🌟