Skip to main content

创建型模式详解

创建型模式关注对象的创建过程,将对象的创建与使用分离,提供灵活的对象创建机制。本章将深入探讨五种创建型模式的原理、实现方式和实际应用。

核心价值

创建型模式 = 封装对象创建 + 灵活实例化 + 创建与使用分离

  • 🔍 隐藏实现细节:屏蔽对象的实例化过程,使系统更专注于业务逻辑
  • 🔄 提高可扩展性:在不修改客户端代码的情况下引入新的具体类型
  • 🛠️ 增强代码复用:避免代码重复,提高代码质量和可维护性
  • 🧩 降低系统耦合度:减少系统各部分的相互依赖

创建型模式概览

1. 单例模式(Singleton)

1.1 模式定义

单例模式确保一个类只有一个实例,并提供一个全局访问点。

  • 资源共享:当需要共享昂贵的资源时(如数据库连接池)
  • 全局状态管理:需要维护全局状态或配置时
  • 协调操作:需要协调系统行为的场景(如日志记录器)

1.2 实现方式

饿汉式单例

饿汉式单例
java
1public class EagerSingleton {
2 // 类加载时就初始化,线程安全
3 private static final EagerSingleton instance = new EagerSingleton();
4
5 // 私有构造函数
6 private EagerSingleton() {
7 // 防止反射攻击
8 if (instance != null) {
9 throw new RuntimeException("单例模式不允许创建多个实例");
10 }
11 }
12
13 // 全局访问点
14 public static EagerSingleton getInstance() {
15 return instance;
16 }
17
18 // 业务方法
19 public void doSomething() {
20 System.out.println("饿汉式单例执行操作");
21 }
22}

懒汉式单例

懒汉式单例
java
1public class LazySingleton {
2 // 延迟初始化
3 private static volatile LazySingleton instance;
4
5 private LazySingleton() {}
6
7 // 双重检查锁定(Double-Checked Locking)
8 public static LazySingleton getInstance() {
9 if (instance == null) {
10 synchronized (LazySingleton.class) {
11 if (instance == null) {
12 instance = new LazySingleton();
13 }
14 }
15 }
16 return instance;
17 }
18
19 public void doSomething() {
20 System.out.println("懒汉式单例执行操作");
21 }
22}

静态内部类单例

静态内部类单例
java
1public class StaticInnerSingleton {
2 private StaticInnerSingleton() {}
3
4 // 静态内部类
5 private static class SingletonHolder {
6 private static final StaticInnerSingleton INSTANCE = new StaticInnerSingleton();
7 }
8
9 public static StaticInnerSingleton getInstance() {
10 return SingletonHolder.INSTANCE;
11 }
12
13 public void doSomething() {
14 System.out.println("静态内部类单例执行操作");
15 }
16}

枚举单例(推荐)

枚举单例
java
1public enum EnumSingleton {
2 INSTANCE;
3
4 public void doSomething() {
5 System.out.println("枚举单例执行操作");
6 }
7
8 // 可以添加其他方法
9 public void anotherMethod() {
10 System.out.println("枚举单例的其他方法");
11 }
12}

1.3 单例模式实现对比

实现方式线程安全延迟加载序列化安全防反射攻击JVM保证推荐指数
饿汉式⭐⭐⭐
懒汉式⭐⭐
静态内部类⭐⭐⭐⭐
枚举方式⭐⭐⭐⭐⭐

1.4 应用场景

配置管理器
java
1public class ConfigurationManager {
2 private static volatile ConfigurationManager instance;
3 private Properties properties;
4
5 private ConfigurationManager() {
6 loadConfiguration();
7 }
8
9 public static ConfigurationManager getInstance() {
10 if (instance == null) {
11 synchronized (ConfigurationManager.class) {
12 if (instance == null) {
13 instance = new ConfigurationManager();
14 }
15 }
16 }
17 return instance;
18 }
19
20 private void loadConfiguration() {
21 properties = new Properties();
22 try (InputStream input = getClass().getClassLoader()
23 .getResourceAsStream("config.properties")) {
24 properties.load(input);
25 } catch (IOException e) {
26 throw new RuntimeException("Failed to load configuration", e);
27 }
28 }
29
30 public String getProperty(String key) {
31 return properties.getProperty(key);
32 }
33}

1.5 实现注意事项

多线程安全性

单例模式在多线程环境中实现时需要特别注意线程安全问题:

  • 懒汉式需要使用双重检查锁定并加上volatile关键字
  • 饿汉式枚举方式天生是线程安全的
  • 避免使用没有同步措施的懒加载方式
最佳实践
  • 推荐优先使用枚举实现单例,简洁且有JVM保证的线程和序列化安全
  • 需要延迟加载时,使用静态内部类方式
  • 考虑使用依赖注入框架来管理单例,而不是手动实现

2. 工厂方法模式(Factory Method)

2.1 模式定义

工厂方法模式定义了一个创建对象的接口,但由子类决定实例化的类是哪一个。工厂方法将类的实例化推迟到子类中进行。

  • 创建逻辑复杂:当对象的创建逻辑较为复杂时
  • 类型多变:当需要创建的对象类型可能在运行时变化时
  • 依赖倒置:想依赖抽象而非具体类时
  • 框架设计:框架需要为用户提供扩展点时

2.2 实现方式

基本工厂方法模式

工厂方法模式
java
1// 抽象产品
2public interface Product {
3 void operation();
4}
5
6// 具体产品A
7public class ConcreteProductA implements Product {
8 @Override
9 public void operation() {
10 System.out.println("产品A的操作");
11 }
12}
13
14// 具体产品B
15public class ConcreteProductB implements Product {
16 @Override
17 public void operation() {
18 System.out.println("产品B的操作");
19 }
20}
21
22// 抽象工厂
23public abstract class Creator {
24 // 工厂方法
25 public abstract Product createProduct();
26
27 // 模板方法
28 public void someOperation() {
29 Product product = createProduct();
30 product.operation();
31 }
32}
33
34// 具体工厂A
35public class ConcreteCreatorA extends Creator {
36 @Override
37 public Product createProduct() {
38 return new ConcreteProductA();
39 }
40}
41
42// 具体工厂B
43public class ConcreteCreatorB extends Creator {
44 @Override
45 public Product createProduct() {
46 return new ConcreteProductB();
47 }
48}

参数化工厂方法

参数化工厂方法
java
1public abstract class Creator {
2 public Product createProduct(String type) {
3 Product product = createProductImpl(type);
4 // 可以在这里添加通用的初始化逻辑
5 return product;
6 }
7
8 protected abstract Product createProductImpl(String type);
9}
10
11public class ConcreteCreator extends Creator {
12 @Override
13 protected Product createProductImpl(String type) {
14 switch (type) {
15 case "A":
16 return new ConcreteProductA();
17 case "B":
18 return new ConcreteProductB();
19 default:
20 throw new IllegalArgumentException("Unknown product type: " + type);
21 }
22 }
23}

2.3 工厂方法模式变体

简单工厂(非GoF设计模式)
java
1public class SimpleFactory {
2 public static Product createProduct(String type) {
3 switch (type) {
4 case "A":
5 return new ConcreteProductA();
6 case "B":
7 return new ConcreteProductB();
8 default:
9 throw new IllegalArgumentException("Unknown product type: " + type);
10 }
11 }
12}
13
14// 使用示例
15public class Client {
16 public void doSomething() {
17 Product product = SimpleFactory.createProduct("A");
18 product.operation();
19 }
20}

简单工厂不属于GoF设计模式,但常作为工厂方法的简化版本使用。

2.4 工厂方法vs简单工厂

特性工厂方法简单工厂
类型GoF设计模式编程习惯
创建方式通过继承通过条件判断
扩展方式添加新的工厂子类修改工厂类代码
开闭原则符合不完全符合
复杂度较高较低
灵活性更灵活较简单
适用场景复杂对象创建、框架设计简单对象创建、小型应用

2.5 应用场景

数据库连接工厂
java
1// 数据库连接接口
2public interface DatabaseConnection {
3 void connect();
4 void disconnect();
5}
6
7// MySQL连接实现
8public class MySQLConnection implements DatabaseConnection {
9 @Override
10 public void connect() {
11 System.out.println("连接MySQL数据库");
12 }
13
14 @Override
15 public void disconnect() {
16 System.out.println("断开MySQL数据库连接");
17 }
18}
19
20// PostgreSQL连接实现
21public class PostgreSQLConnection implements DatabaseConnection {
22 @Override
23 public void connect() {
24 System.out.println("连接PostgreSQL数据库");
25 }
26
27 @Override
28 public void disconnect() {
29 System.out.println("断开PostgreSQL数据库连接");
30 }
31}
32
33// 数据库连接工厂接口
34public abstract class DatabaseConnectionFactory {
35 public abstract DatabaseConnection createConnection();
36
37 public DatabaseConnection getConnection() {
38 DatabaseConnection connection = createConnection();
39 // 可以在这里添加连接池管理逻辑
40 return connection;
41 }
42}
43
44// MySQL连接工厂
45public class MySQLConnectionFactory extends DatabaseConnectionFactory {
46 @Override
47 public DatabaseConnection createConnection() {
48 return new MySQLConnection();
49 }
50}
51
52// PostgreSQL连接工厂
53public class PostgreSQLConnectionFactory extends DatabaseConnectionFactory {
54 @Override
55 public DatabaseConnection createConnection() {
56 return new PostgreSQLConnection();
57 }
58}
工厂方法模式最佳实践
  1. 命名清晰:为工厂方法使用描述性名称,如createXXXnewXXXgetXXX
  2. 预初始化:可以在工厂方法中对创建的对象进行预初始化或验证
  3. 层次平衡:避免创建过深的工厂继承层次
  4. 单一职责:一个工厂类只负责创建一种类型的产品
  5. 参数控制:根据需要选择使用参数化工厂方法或专用工厂子类

3. 抽象工厂模式(Abstract Factory)

3.1 模式定义

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。它是工厂方法模式的扩展,用于创建产品族。

  • 产品族创建:需要创建一系列相关产品时
  • 一致性保证:需要确保创建的产品彼此兼容
  • 平台独立:系统需要与多个平台或技术集成
  • 隔离变化:隔离产品创建的具体细节

3.2 实现示例

抽象工厂模式
java
1// 抽象产品A
2public interface AbstractProductA {
3 void operationA();
4}
5
6// 抽象产品B
7public interface AbstractProductB {
8 void operationB();
9}
10
11// 具体产品A1
12public class ConcreteProductA1 implements AbstractProductA {
13 @Override
14 public void operationA() {
15 System.out.println("产品A1的操作");
16 }
17}
18
19// 具体产品A2
20public class ConcreteProductA2 implements AbstractProductA {
21 @Override
22 public void operationA() {
23 System.out.println("产品A2的操作");
24 }
25}
26
27// 具体产品B1
28public class ConcreteProductB1 implements AbstractProductB {
29 @Override
30 public void operationB() {
31 System.out.println("产品B1的操作");
32 }
33}
34
35// 具体产品B2
36public class ConcreteProductB2 implements AbstractProductB {
37 @Override
38 public void operationB() {
39 System.out.println("产品B2的操作");
40 }
41}
42
43// 抽象工厂
44public interface AbstractFactory {
45 AbstractProductA createProductA();
46 AbstractProductB createProductB();
47}
48
49// 具体工厂1
50public class ConcreteFactory1 implements AbstractFactory {
51 @Override
52 public AbstractProductA createProductA() {
53 return new ConcreteProductA1();
54 }
55
56 @Override
57 public AbstractProductB createProductB() {
58 return new ConcreteProductB1();
59 }
60}
61
62// 具体工厂2
63public class ConcreteFactory2 implements AbstractFactory {
64 @Override
65 public AbstractProductA createProductA() {
66 return new ConcreteProductA2();
67 }
68
69 @Override
70 public AbstractProductB createProductB() {
71 return new ConcreteProductB2();
72 }
73}

3.3 抽象工厂与工厂方法对比

特性抽象工厂工厂方法
目的创建产品族创建单个产品
接口多个创建方法单个创建方法
扩展产品族容易(增加工厂类)不适用
扩展产品种类困难(修改接口)容易(增加产品类)
抽象层次更高较低
复杂度更复杂较简单
适用场景多系列产品集成单一产品创建

3.4 应用场景

UI组件抽象工厂
java
1// 按钮接口
2public interface Button {
3 void render();
4 void onClick();
5}
6
7// 复选框接口
8public interface Checkbox {
9 void render();
10 boolean isChecked();
11}
12
13// Windows风格按钮
14public class WindowsButton implements Button {
15 @Override
16 public void render() {
17 System.out.println("渲染Windows风格按钮");
18}
19
20 @Override
21 public void onClick() {
22 System.out.println("Windows按钮点击事件");
23 }
24}
25
26// Windows风格复选框
27public class WindowsCheckbox implements Checkbox {
28 private boolean checked = false;
29
30 @Override
31 public void render() {
32 System.out.println("渲染Windows风格复选框");
33 }
34
35 @Override
36 public boolean isChecked() {
37 return checked;
38 }
39}
40
41// macOS风格按钮
42public class MacButton implements Button {
43 @Override
44 public void render() {
45 System.out.println("渲染macOS风格按钮");
46 }
47
48 @Override
49 public void onClick() {
50 System.out.println("macOS按钮点击事件");
51 }
52}
53
54// macOS风格复选框
55public class MacCheckbox implements Checkbox {
56 private boolean checked = false;
57
58 @Override
59 public void render() {
60 System.out.println("渲染macOS风格复选框");
61 }
62
63 @Override
64 public boolean isChecked() {
65 return checked;
66 }
67}
68
69// UI工厂接口
70public interface UIFactory {
71 Button createButton();
72 Checkbox createCheckbox();
73}
74
75// Windows UI工厂
76public class WindowsUIFactory implements UIFactory {
77 @Override
78 public Button createButton() {
79 return new WindowsButton();
80 }
81
82 @Override
83 public Checkbox createCheckbox() {
84 return new WindowsCheckbox();
85 }
86}
87
88// macOS UI工厂
89public class MacUIFactory implements UIFactory {
90 @Override
91 public Button createButton() {
92 return new MacButton();
93 }
94
95 @Override
96 public Checkbox createCheckbox() {
97 return new MacCheckbox();
98 }
99}
100
101// 客户端应用
102public class Application {
103 private Button button;
104 private Checkbox checkbox;
105
106 public Application(UIFactory factory) {
107 button = factory.createButton();
108 checkbox = factory.createCheckbox();
109 }
110
111 public void render() {
112 button.render();
113 checkbox.render();
114 }
115}
116
117// 根据操作系统选择工厂
118public class ApplicationRunner {
119 public static void main(String[] args) {
120 UIFactory factory;
121 String osName = System.getProperty("os.name").toLowerCase();
122
123 if (osName.contains("windows")) {
124 factory = new WindowsUIFactory();
125 } else {
126 factory = new MacUIFactory();
127 }
128
129 Application app = new Application(factory);
130 app.render();
131 }
132}

3.5 抽象工厂模式的变体

带有工厂方法的抽象工厂

带有工厂方法的抽象工厂
java
1public abstract class AbstractFactory {
2 public abstract Button createButton();
3 public abstract Checkbox createCheckbox();
4
5 // 静态工厂方法
6 public static AbstractFactory getFactory(String type) {
7 if ("windows".equalsIgnoreCase(type)) {
8 return new WindowsUIFactory();
9 } else if ("mac".equalsIgnoreCase(type)) {
10 return new MacUIFactory();
11 } else {
12 throw new IllegalArgumentException("Unknown UI type: " + type);
13 }
14 }
15}

使用反射的抽象工厂

使用反射的抽象工厂
java
1public class ReflectiveFactory implements AbstractFactory {
2 private Class<?> buttonClass;
3 private Class<?> checkboxClass;
4
5 public ReflectiveFactory(String buttonClassName, String checkboxClassName)
6 throws ClassNotFoundException {
7 this.buttonClass = Class.forName(buttonClassName);
8 this.checkboxClass = Class.forName(checkboxClassName);
9 }
10
11 @Override
12 public Button createButton() {
13 try {
14 return (Button) buttonClass.newInstance();
15 } catch (Exception e) {
16 throw new RuntimeException("Cannot create button", e);
17 }
18 }
19
20 @Override
21 public Checkbox createCheckbox() {
22 try {
23 return (Checkbox) checkboxClass.newInstance();
24 } catch (Exception e) {
25 throw new RuntimeException("Cannot create checkbox", e);
26 }
27 }
28}
抽象工厂最佳实践
  1. 产品族划分:按照产品之间的关联性和一致性进行合理划分
  2. 接口设计:设计清晰、内聚的接口,避免过于臃肿的抽象工厂接口
  3. 工厂扩展:考虑使用工厂方法或简单工厂来创建抽象工厂实例
  4. 产品扩展:预留产品种类扩展的机制,例如使用默认实现或可选方法
  5. 配置驱动:考虑使用配置文件或反射机制来动态选择工厂实现

4. 建造者模式(Builder)

4.1 模式定义

建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。它允许我们分步骤创建复杂对象,并能轻松控制创建过程。

  • 复杂对象创建:对象具有复杂的内部结构或多个组成部分
  • 不同表示:同一个对象在不同场景下有不同的表示形式
  • 分步构建:需要对象的创建过程可控且灵活
  • 参数校验:需要在对象创建时进行复杂的参数校验

4.2 实现方式

基本建造者模式

建造者模式
java
1// 产品类
2public class Computer {
3 private String cpu;
4 private String memory;
5 private String storage;
6 private String graphics;
7 private String motherboard;
8
9 // 私有构造函数
10 private Computer() {}
11
12 // Getter方法
13 public String getCpu() { return cpu; }
14 public String getMemory() { return memory; }
15 public String getStorage() { return storage; }
16 public String getGraphics() { return graphics; }
17 public String getMotherboard() { return motherboard; }
18
19 @Override
20 public String toString() {
21 return String.format("Computer{cpu='%s', memory='%s', storage='%s', graphics='%s', motherboard='%s'}",
22 cpu, memory, storage, graphics, motherboard);
23 }
24
25 // 静态内部建造者类
26 public static class Builder {
27 private Computer computer = new Computer();
28
29 public Builder cpu(String cpu) {
30 computer.cpu = cpu;
31 return this;
32 }
33
34 public Builder memory(String memory) {
35 computer.memory = memory;
36 return this;
37 }
38
39 public Builder storage(String storage) {
40 computer.storage = storage;
41 return this;
42 }
43
44 public Builder graphics(String graphics) {
45 computer.graphics = graphics;
46 return this;
47 }
48
49 public Builder motherboard(String motherboard) {
50 computer.motherboard = motherboard;
51 return this;
52 }
53
54 public Computer build() {
55 // 参数校验
56 validate();
57 return computer;
58 }
59
60 private void validate() {
61 if (computer.cpu == null) {
62 throw new IllegalArgumentException("CPU不能为空");
63 }
64 if (computer.memory == null) {
65 throw new IllegalArgumentException("内存不能为空");
66 }
67 if (computer.storage == null) {
68 throw new IllegalArgumentException("存储不能为空");
69 }
70 }
71 }
72}

使用指导者的建造者模式

带指导者的建造者模式
java
1// 产品类
2public class House {
3 private String foundation;
4 private String structure;
5 private String roof;
6 private String interior;
7
8 public void setFoundation(String foundation) {
9 this.foundation = foundation;
10 }
11
12 public void setStructure(String structure) {
13 this.structure = structure;
14 }
15
16 public void setRoof(String roof) {
17 this.roof = roof;
18 }
19
20 public void setInterior(String interior) {
21 this.interior = interior;
22 }
23
24 @Override
25 public String toString() {
26 return String.format("House{foundation='%s', structure='%s', roof='%s', interior='%s'}",
27 foundation, structure, roof, interior);
28 }
29}
30
31// 抽象建造者
32public interface HouseBuilder {
33 void buildFoundation();
34 void buildStructure();
35 void buildRoof();
36 void buildInterior();
37 House getResult();
38}
39
40// 具体建造者 - 砖房
41public class BrickHouseBuilder implements HouseBuilder {
42 private House house = new House();
43
44 @Override
45 public void buildFoundation() {
46 house.setFoundation("混凝土地基");
47 }
48
49 @Override
50 public void buildStructure() {
51 house.setStructure("砖墙结构");
52 }
53
54 @Override
55 public void buildRoof() {
56 house.setRoof("平屋顶");
57 }
58
59 @Override
60 public void buildInterior() {
61 house.setInterior("标准内部装修");
62 }
63
64 @Override
65 public House getResult() {
66 return house;
67 }
68}
69
70// 具体建造者 - 木房
71public class WoodenHouseBuilder implements HouseBuilder {
72 private House house = new House();
73
74 @Override
75 public void buildFoundation() {
76 house.setFoundation("条形地基");
77 }
78
79 @Override
80 public void buildStructure() {
81 house.setStructure("木质框架结构");
82 }
83
84 @Override
85 public void buildRoof() {
86 house.setRoof("坡屋顶");
87 }
88
89 @Override
90 public void buildInterior() {
91 house.setInterior("木质内部装修");
92 }
93
94 @Override
95 public House getResult() {
96 return house;
97 }
98}
99
100// 指导者
101public class HouseDirector {
102 private HouseBuilder builder;
103
104 public HouseDirector(HouseBuilder builder) {
105 this.builder = builder;
106 }
107
108 public void changeBuilder(HouseBuilder builder) {
109 this.builder = builder;
110 }
111
112 // 构建完整的房子
113 public House buildFullFeaturedHouse() {
114 builder.buildFoundation();
115 builder.buildStructure();
116 builder.buildRoof();
117 builder.buildInterior();
118 return builder.getResult();
119 }
120
121 // 构建简易的房子
122 public House buildMinimalHouse() {
123 builder.buildFoundation();
124 builder.buildStructure();
125 builder.buildRoof();
126 return builder.getResult();
127 }
128}
129
130// 客户端代码
131public class BuilderPatternDemo {
132 public static void main(String[] args) {
133 HouseBuilder brickBuilder = new BrickHouseBuilder();
134 HouseBuilder woodenBuilder = new WoodenHouseBuilder();
135
136 HouseDirector director = new HouseDirector(brickBuilder);
137
138 // 构建砖房
139 House brickHouse = director.buildFullFeaturedHouse();
140 System.out.println("砖房: " + brickHouse);
141
142 // 切换建造者,构建木房
143 director.changeBuilder(woodenBuilder);
144 House woodenHouse = director.buildMinimalHouse();
145 System.out.println("简易木房: " + woodenHouse);
146 }
147}

4.3 建造者模式变体

流式建造者模式(链式调用)

流式建造者
java
1// 使用示例
2public class BuilderExample {
3 public static void main(String[] args) {
4 // 构建高性能电脑
5 Computer gamingComputer = new Computer.Builder()
6 .cpu("Intel i9-12900K")
7 .memory("32GB DDR5")
8 .storage("2TB NVMe SSD")
9 .graphics("RTX 4090")
10 .motherboard("Z690")
11 .build();
12
13 System.out.println("游戏电脑: " + gamingComputer);
14
15 // 构建办公电脑
16 Computer officeComputer = new Computer.Builder()
17 .cpu("Intel i5-12400")
18 .memory("16GB DDR4")
19 .storage("512GB SSD")
20 .graphics("集成显卡")
21 .motherboard("B660")
22 .build();
23
24 System.out.println("办公电脑: " + officeComputer);
25 }
26}

步进式建造者模式

步进式建造者
java
1public class StepBuilder {
2 // 步进接口
3 public interface CpuStep {
4 MemoryStep cpu(String cpu);
5 }
6
7 public interface MemoryStep {
8 StorageStep memory(String memory);
9 }
10
11 public interface StorageStep {
12 OptionalStep storage(String storage);
13 }
14
15 public interface OptionalStep {
16 OptionalStep graphics(String graphics);
17 OptionalStep motherboard(String motherboard);
18 Computer build();
19 }
20
21 // 实现类
22 public static class ComputerBuilder implements CpuStep, MemoryStep, StorageStep, OptionalStep {
23 private Computer computer = new Computer();
24
25 private ComputerBuilder() {}
26
27 public static CpuStep newBuilder() {
28 return new ComputerBuilder();
29 }
30
31 @Override
32 public MemoryStep cpu(String cpu) {
33 computer.setCpu(cpu);
34 return this;
35 }
36
37 @Override
38 public StorageStep memory(String memory) {
39 computer.setMemory(memory);
40 return this;
41 }
42
43 @Override
44 public OptionalStep storage(String storage) {
45 computer.setStorage(storage);
46 return this;
47 }
48
49 @Override
50 public OptionalStep graphics(String graphics) {
51 computer.setGraphics(graphics);
52 return this;
53 }
54
55 @Override
56 public OptionalStep motherboard(String motherboard) {
57 computer.setMotherboard(motherboard);
58 return this;
59 }
60
61 @Override
62 public Computer build() {
63 return computer;
64 }
65 }
66}
67
68// 使用步进式建造者
69Computer computer = StepBuilder.ComputerBuilder.newBuilder()
70 .cpu("Intel i7") // 必须的
71 .memory("16GB DDR4") // 必须的
72 .storage("1TB SSD") // 必须的
73 .graphics("RTX 3080") // 可选的
74 .build();

4.4 应用场景

数据库配置建造者
java
1public class DatabaseConfig {
2 private String host;
3 private int port;
4 private String database;
5 private String username;
6 private String password;
7 private int maxConnections;
8 private int timeout;
9
10 private DatabaseConfig() {}
11
12 // Getter方法...
13
14 public static class Builder {
15 private DatabaseConfig config = new DatabaseConfig();
16
17 public Builder host(String host) {
18 config.host = host;
19 return this;
20 }
21
22 public Builder port(int port) {
23 config.port = port;
24 return this;
25 }
26
27 public Builder database(String database) {
28 config.database = database;
29 return this;
30 }
31
32 public Builder username(String username) {
33 config.username = username;
34 return this;
35 }
36
37 public Builder password(String password) {
38 config.password = password;
39 return this;
40 }
41
42 public Builder maxConnections(int maxConnections) {
43 config.maxConnections = maxConnections;
44 return this;
45 }
46
47 public Builder timeout(int timeout) {
48 config.timeout = timeout;
49 return this;
50 }
51
52 public DatabaseConfig build() {
53 // 设置默认值
54 if (config.port == 0) {
55 config.port = 3306;
56 }
57 if (config.maxConnections == 0) {
58 config.maxConnections = 10;
59 }
60 if (config.timeout == 0) {
61 config.timeout = 30;
62 }
63
64 validate();
65 return config;
66 }
67
68 private void validate() {
69 if (config.host == null || config.host.trim().isEmpty()) {
70 throw new IllegalArgumentException("主机地址不能为空");
71 }
72 if (config.database == null || config.database.trim().isEmpty()) {
73 throw new IllegalArgumentException("数据库名不能为空");
74 }
75 if (config.username == null || config.username.trim().isEmpty()) {
76 throw new IllegalArgumentException("用户名不能为空");
77 }
78 }
79 }
80}
81
82// 使用示例
83DatabaseConfig config = new DatabaseConfig.Builder()
84 .host("localhost")
85 .port(3306)
86 .database("mydb")
87 .username("user")
88 .password("pass")
89 .maxConnections(20)
90 .build();

4.5 建造者模式与其他模式的对比

特性建造者模式工厂方法抽象工厂
目的分步创建复杂对象创建单个产品创建产品族
关注点创建过程和步骤产品类型产品族和兼容性
可控性高(分步构建)低(一次创建)中(关联创建)
复杂度中等较低
链式API支持通常不支持通常不支持
参数校验集中处理分散处理分散处理
建造者模式最佳实践
  1. 适当的封装:使用私有构造函数强制通过建造者创建对象
  2. 参数校验:在build()方法中集中进行参数验证
  3. 默认值处理:为非必须参数提供合理的默认值
  4. 方法命名:使用描述性的方法名,使构建过程更易读
  5. 建造者内置:考虑将建造者类设计为产品类的内部类
  6. 流式接口:支持方法链(链式调用)以提高代码可读性

5. 原型模式(Prototype)

5.1 模式定义

原型模式通过复制现有对象来创建新对象,而不是通过实例化类。当创建对象的成本较高,且对象之间存在相似性时,使用原型模式可以提高性能并简化对象创建过程。

  • 创建成本高:当对象创建过程复杂或代价高昂时
  • 避免继承:当系统应该独立于产品创建、组合和表示时
  • 动态配置:运行时需要动态添加和移除产品时
  • 避免重复初始化:需要创建与现有对象相似的对象时

5.2 实现方式

基本原型模式

原型模式
java
1// 原型接口
2public interface Prototype extends Cloneable {
3 Prototype clone();
4 void display();
5}
6
7// 具体原型
8public class ConcretePrototype implements Prototype {
9 private String name;
10 private List<String> attributes = new ArrayList<>();
11
12 public ConcretePrototype(String name) {
13 this.name = name;
14 this.attributes.add("属性1");
15 this.attributes.add("属性2");
16 }
17
18 @Override
19 public Prototype clone() {
20 try {
21 ConcretePrototype clone = (ConcretePrototype) super.clone();
22 // 深拷贝
23 clone.attributes = new ArrayList<>(this.attributes);
24 return clone;
25 } catch (CloneNotSupportedException e) {
26 throw new RuntimeException(e);
27 }
28 }
29
30 @Override
31 public void display() {
32 System.out.println("原型名称: " + name);
33 System.out.println("属性: " + attributes);
34 }
35
36 public void addAttribute(String attribute) {
37 this.attributes.add(attribute);
38 }
39
40 public void setName(String name) {
41 this.name = name;
42 }
43}

原型管理器

原型管理器
java
1public class PrototypeManager {
2 private Map<String, Prototype> prototypes = new HashMap<>();
3
4 public void addPrototype(String key, Prototype prototype) {
5 prototypes.put(key, prototype);
6 }
7
8 public Prototype getPrototype(String key) {
9 Prototype prototype = prototypes.get(key);
10 if (prototype != null) {
11 return prototype.clone();
12 }
13 return null;
14 }
15
16 public void removePrototype(String key) {
17 prototypes.remove(key);
18 }
19}
20
21// 使用示例
22public class PrototypeExample {
23 public static void main(String[] args) {
24 PrototypeManager manager = new PrototypeManager();
25
26 // 添加原型
27 ConcretePrototype prototype1 = new ConcretePrototype("原型1");
28 manager.addPrototype("type1", prototype1);
29
30 // 克隆原型
31 Prototype clone1 = manager.getPrototype("type1");
32 Prototype clone2 = manager.getPrototype("type1");
33
34 // 修改克隆对象
35 if (clone1 instanceof ConcretePrototype) {
36 ((ConcretePrototype) clone1).setName("克隆1");
37 ((ConcretePrototype) clone1).addAttribute("新属性");
38 }
39
40 // 显示结果
41 prototype1.display();
42 clone1.display();
43 clone2.display();
44 }
45}

5.3 深拷贝与浅拷贝

浅拷贝实现
java
1public class ShallowCopy implements Cloneable {
2 private String name;
3 private List<String> items;
4
5 public ShallowCopy(String name) {
6 this.name = name;
7 this.items = new ArrayList<>();
8 }
9
10 public void addItem(String item) {
11 items.add(item);
12 }
13
14 @Override
15 public ShallowCopy clone() {
16 try {
17 // 浅拷贝:引用类型成员变量共享引用
18 return (ShallowCopy) super.clone();
19 } catch (CloneNotSupportedException e) {
20 throw new RuntimeException(e);
21 }
22 }
23
24 @Override
25 public String toString() {
26 return "ShallowCopy{name='" + name + "', items=" + items + "}";
27 }
28
29 // Getter和Setter方法
30 public String getName() { return name; }
31 public void setName(String name) { this.name = name; }
32 public List<String> getItems() { return items; }
33}
34
35// 使用示例
36ShallowCopy original = new ShallowCopy("原始对象");
37original.addItem("条目1");
38original.addItem("条目2");
39
40ShallowCopy clone = original.clone();
41clone.setName("克隆对象");
42clone.getItems().add("条目3"); // 修改克隆对象的列表
43
44System.out.println("原始对象: " + original); // 输出也包含"条目3"
45System.out.println("克隆对象: " + clone);

5.4 应用场景

文档模板系统
java
1public abstract class Document implements Cloneable {
2 protected String title;
3 protected String content;
4 protected List<String> sections = new ArrayList<>();
5
6 public abstract void display();
7
8 @Override
9 public Document clone() {
10 try {
11 Document clone = (Document) super.clone();
12 // 深拷贝
13 clone.sections = new ArrayList<>(this.sections);
14 return clone;
15 } catch (CloneNotSupportedException e) {
16 throw new RuntimeException(e);
17 }
18 }
19
20 public void setTitle(String title) {
21 this.title = title;
22 }
23
24 public void setContent(String content) {
25 this.content = content;
26 }
27
28 public void addSection(String section) {
29 this.sections.add(section);
30 }
31}
32
33public class ReportDocument extends Document {
34 @Override
35 public void display() {
36 System.out.println("报告文档: " + title);
37 System.out.println("内容: " + content);
38 System.out.println("章节: " + sections);
39 }
40}
41
42public class ProposalDocument extends Document {
43 @Override
44 public void display() {
45 System.out.println("提案文档: " + title);
46 System.out.println("内容: " + content);
47 System.out.println("章节: " + sections);
48 }
49}
50
51// 文档模板管理器
52public class DocumentTemplateManager {
53 private Map<String, Document> templates = new HashMap<>();
54
55 public void addTemplate(String name, Document template) {
56 templates.put(name, template);
57 }
58
59 public Document createDocument(String templateName) {
60 Document template = templates.get(templateName);
61 if (template != null) {
62 return template.clone();
63 }
64 return null;
65 }
66}

5.5 原型模式与其他模式对比

特性原型模式工厂方法建造者模式
创建机制克隆现有对象创建新对象分步构建对象
复杂度低(直接复制)中等高(多步骤)
使用时机避免重复初始化封装创建逻辑复杂对象构建
实现方法实现clone()方法子类化创建者构建器或指导者
优势性能好,避免初始化扩展性好灵活性高,参数控制
劣势深拷贝复杂类爆炸代码量增加
原型模式最佳实践
  1. 优先使用深拷贝:确保对象及其内部对象都被正确克隆
  2. 处理特殊引用:注意处理循环引用和不可克隆的对象
  3. 使用序列化:对于复杂对象,可以使用序列化实现深拷贝
  4. 避免副作用:确保克隆操作不会对原对象产生副作用
  5. 模板注册中心:使用原型管理器注册和管理原型对象

6. 创建型模式对比

6.1 模式选择指南

模式适用场景优点缺点
单例模式全局唯一实例节省内存,全局访问可能成为全局状态
工厂方法延迟实例化,扩展产品符合开闭原则增加类的数量
抽象工厂产品族创建保证产品兼容性扩展新产品族困难
建造者复杂对象构建参数校验,链式调用增加代码复杂度
原型对象克隆避免重复初始化深拷贝开销

6.2 性能考虑

创建型模式在性能上各有优劣,选择合适的模式需要考虑应用场景和性能需求:

性能对比示例
java
1// 单例模式 - 内存占用最小
2public class SingletonExample {
3 private static SingletonExample instance;
4
5 public static SingletonExample getInstance() {
6 if (instance == null) {
7 instance = new SingletonExample();
8 }
9 return instance;
10 }
11}
12
13// 工厂模式 - 对象创建开销
14public class FactoryExample {
15 public Product createProduct(String type) {
16 // 每次调用都可能创建新对象
17 switch (type) {
18 case "A": return new ProductA();
19 case "B": return new ProductB();
20 default: throw new IllegalArgumentException();
21 }
22 }
23}
24
25// 原型模式 - 克隆开销
26public class PrototypeExample implements Cloneable {
27 private List<String> data = new ArrayList<>();
28
29 @Override
30 public PrototypeExample clone() {
31 try {
32 PrototypeExample clone = (PrototypeExample) super.clone();
33 // 深拷贝开销
34 clone.data = new ArrayList<>(this.data);
35 return clone;
36 } catch (CloneNotSupportedException e) {
37 throw new RuntimeException(e);
38 }
39 }
40}
模式内存使用描述
单例⭐⭐⭐⭐⭐最优(只有一个实例)
工厂方法⭐⭐⭐中等(每次创建新对象)
抽象工厂⭐⭐⭐中等(每个产品族创建多个对象)
建造者⭐⭐较高(中间状态占用内存)
原型⭐⭐⭐⭐良好(复用现有对象结构)

6.3 设计模式组合使用

创建型模式常常组合使用以获取更好的设计效果:

  1. 工厂方法+单例:工厂本身是单例,确保工厂全局唯一
  2. 抽象工厂+工厂方法:用工厂方法实现抽象工厂
  3. 建造者+原型:用原型模式复制建造者创建的基础对象
  4. 单例+原型:单例管理器存储原型对象
  5. 抽象工厂+建造者:工厂创建建造者对象
组合模式示例
java
1// 单例工厂示例
2public class SingletonFactory {
3 private static SingletonFactory instance = new SingletonFactory();
4 private Map<String, Product> products = new HashMap<>();
5
6 private SingletonFactory() {
7 // 注册产品原型
8 products.put("default", new ConcreteProduct());
9 }
10
11 public static SingletonFactory getInstance() {
12 return instance;
13 }
14
15 public Product createProduct(String type) {
16 Product prototype = products.get(type);
17 if (prototype == null) {
18 prototype = products.get("default");
19 }
20 // 使用原型模式创建产品
21 return prototype.clone();
22 }
23}
创建型模式选择原则
  1. 单例模式:需要全局唯一实例时使用
  2. 工厂方法:需要延迟实例化时使用
  3. 抽象工厂:需要创建产品族时使用
  4. 建造者模式:需要构建复杂对象时使用
  5. 原型模式:需要对象克隆时使用

通过本章的学习,你应该已经掌握了五种创建型模式的原理、实现方式和应用场景。在实际项目中,要根据具体需求选择合适的创建型模式,并注意线程安全和性能优化问题。

参与讨论