创建型设计模式提供了创建对象的机制, 能够提升已有代码的灵活性和可复用性。
工厂模式
简单工厂模式
定义:通过一个工厂类,根据传入的参数动态决定创建哪种具体产品类的实例。
适用场景:产品种类较少且变化不频繁的场景。
结构
classDiagram
class Product {
<<interface>>
+use()
}
class ConcreteProductA {
+use()
}
class ConcreteProductB {
+use()
}
class SimpleFactory {
+createProduct(String type): Product
}
SimpleFactory --> Product : 创建
Product <|.. ConcreteProductA : 实现
Product <|.. ConcreteProductB : 实现
代码示例
// 抽象产品接口
interface Product {
void use();
}
// 具体产品A
class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("使用产品A");
}
}
// 具体产品B
class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("使用产品B");
}
}
// 简单工厂类
class SimpleFactory {
public Product createProduct(String type) {
if ("A".equals(type)) {
return new ConcreteProductA();
} else if ("B".equals(type)) {
return new ConcreteProductB();
}
throw new IllegalArgumentException("未知产品类型");
}
}
// 客户端
public class Client {
public static void main(String[] args) {
SimpleFactory factory = new SimpleFactory();
Product productA = factory.createProduct("A");
productA.use(); // 输出:使用产品A
}
}
工厂方法模式
定义:定义一个创建对象的接口,但由子类决定实例化哪个类。将对象的创建延迟到子类。
适用场景:需要支持多种产品类型且可能频繁扩展的场景。
结构
classDiagram
class Product {
<<interface>>
+use()
}
class ConcreteProductA {
+use()
}
class ConcreteProductB {
+use()
}
class Factory {
<<abstract>>
+createProduct(): Product
}
class ConcreteFactoryA {
+createProduct(): Product
}
class ConcreteFactoryB {
+createProduct(): Product
}
Factory <|-- ConcreteFactoryA : 继承
Factory <|-- ConcreteFactoryB : 继承
ConcreteFactoryA --> ConcreteProductA : 创建
ConcreteFactoryB --> ConcreteProductB : 创建
Product <|.. ConcreteProductA : 实现
Product <|.. ConcreteProductB : 实现
代码示例
// 抽象产品接口
interface Product {
void use();
}
// 具体产品A
class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("使用产品A");
}
}
// 具体产品B
class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("使用产品B");
}
}
// 抽象工厂接口
interface Factory {
Product createProduct();
}
// 具体工厂A
class ConcreteFactoryA implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
// 具体工厂B
class ConcreteFactoryB implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Factory factoryA = new ConcreteFactoryA();
Product productA = factoryA.createProduct();
productA.use(); // 输出:使用产品A
Factory factoryB = new ConcreteFactoryB();
Product productB = factoryB.createProduct();
productB.use(); // 输出:使用产品B
}
}
抽象工厂模式
定义:提供一个接口,用于创建相关或依赖对象的家族,而无需指定具体类。
适用场景:需要创建一组相关或依赖对象的场景(如跨平台UI组件库)。
结构
classDiagram
class AbstractFactory {
<<interface>>
+createButton(): Button
+createTextField(): TextField
}
class WindowsFactory {
+createButton(): WindowsButton
+createTextField(): WindowsTextField
}
class MacFactory {
+createButton(): MacButton
+createTextField(): MacTextField
}
class Button {
<<interface>>
+render()
}
class WindowsButton {
+render()
}
class MacButton {
+render()
}
class TextField {
<<interface>>
+display()
}
class WindowsTextField {
+display()
}
class MacTextField {
+display()
}
AbstractFactory <|.. WindowsFactory : 实现
AbstractFactory <|.. MacFactory : 实现
Button <|.. WindowsButton : 实现
Button <|.. MacButton : 实现
TextField <|.. WindowsTextField : 实现
TextField <|.. MacTextField : 实现
WindowsFactory --> WindowsButton : 创建
WindowsFactory --> WindowsTextField : 创建
MacFactory --> MacButton : 创建
MacFactory --> MacTextField : 创建
代码示例
// 抽象产品族A
interface Button {
void render();
}
// 具体产品A1:Windows按钮
class WindowsButton implements Button {
@Override
public void render() {
System.out.println("渲染Windows风格按钮");
}
}
// 具体产品A2:Mac按钮
class MacButton implements Button {
@Override
public void render() {
System.out.println("渲染Mac风格按钮");
}
}
// 抽象产品族B
interface TextField {
void display();
}
// 具体产品B1:Windows文本框
class WindowsTextField implements TextField {
@Override
public void display() {
System.out.println("显示Windows风格文本框");
}
}
// 具体产品B2:Mac文本框
class MacTextField implements TextField {
@Override
public void display() {
System.out.println("显示Mac风格文本框");
}
}
// 抽象工厂接口
interface GUIFactory {
Button createButton();
TextField createTextField();
}
// 具体工厂1:Windows工厂
class WindowsFactory implements GUIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public TextField createTextField() {
return new WindowsTextField();
}
}
// 具体工厂2:Mac工厂
class MacFactory implements GUIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public TextField createTextField() {
return new MacTextField();
}
}
// 客户端
public class Client {
public static void main(String[] args) {
GUIFactory windowsFactory = new WindowsFactory();
Button winButton = windowsFactory.createButton();
TextField winTextField = windowsFactory.createTextField();
winButton.render(); // 输出:渲染Windows风格按钮
winTextField.display(); // 输出:显示Windows风格文本框
GUIFactory macFactory = new MacFactory();
Button macButton = macFactory.createButton();
TextField macTextField = macFactory.createTextField();
macButton.render(); // 输出:渲染Mac风格按钮
macTextField.display(); // 输出:显示Mac风格文本框
}
}
工厂模式对比
| 模式 | 核心特点 | 扩展性 | 适用场景 |
|---|---|---|---|
| 简单工厂 | 单工厂类,通过参数创建不同产品 | 差(需修改工厂类) | 产品类型少且不频繁变化 |
| 工厂方法 | 每个产品对应一个工厂子类 | 好(新增子类即可) | 需要灵活扩展产品类型的场景 |
| 抽象工厂 | 生产多个相关产品组成的家族 | 中等(产品族难扩展) | 需要保证产品兼容性的复杂系统 |
生成器设计模式
模式定义
生成器模式是一种创建型设计模式,用于分步骤构建复杂对象。它通过将对象的构建过程与其表示分离,使得相同的构建过程可以创建不同的对象表示。该模式特别适用于需要多个配置参数或构建步骤的对象,避免了冗长的构造函数参数列表(称为“重叠构造函数”问题),并提高了代码的可读性和灵活性。
核心角色
生成器模式包含以下关键角色:
| 角色 | 说明 |
|---|---|
| 产品(Product) | 最终要构建的复杂对象,包含多个组成部分(如电脑的 CPU、内存、硬盘)。 |
| 生成器(Builder) | 定义构建产品各部分的抽象接口(如 setCPU()、setRAM())。 |
| 具体生成器(Concrete Builder) | 实现生成器接口,提供构建各部分的具体逻辑,并返回最终产品。 |
| 指挥者(Director) | 可选角色,负责调用生成器的步骤方法,控制构建流程(如组装电脑的标准流程)。 |
结构
classDiagram
class Product {
-cpu: String
-ram: String
-storage: String
+toString(): String
}
class Builder {
<<interface>>
+buildCPU(String cpu): void
+buildRAM(String ram): void
+buildStorage(String storage): void
+getResult(): Product
}
class ComputerBuilder {
-product: Product
+buildCPU(String cpu): void
+buildRAM(String ram): void
+buildStorage(String storage): void
+getResult(): Product
}
class Director {
-builder: Builder
+construct(): void
}
Product <-- ComputerBuilder : 创建
Builder <|.. ComputerBuilder : 实现
Director --> Builder : 使用
代码示例
以“组装电脑”为例,演示生成器模式的应用:
// 步骤1:定义产品类(Computer)
public class Computer {
private String cpu;
private String ram;
private String storage;
public void setCpu(String cpu) { this.cpu = cpu; }
public void setRam(String ram) { this.ram = ram; }
public void setStorage(String storage) { this.storage = storage; }
@Override
public String toString() {
return "Computer [CPU=" + cpu + ", RAM=" + ram + ", Storage=" + storage + "]";
}
}
// 步骤2:定义生成器接口(ComputerBuilder)
public interface ComputerBuilder {
void buildCPU(String cpu);
void buildRAM(String ram);
void buildStorage(String storage);
Computer getResult();
}
// 步骤3:实现具体生成器(StandardComputerBuilder)
public class StandardComputerBuilder implements ComputerBuilder {
private Computer computer = new Computer();
@Override
public void buildCPU(String cpu) {
computer.setCpu(cpu);
}
@Override
public void buildRAM(String ram) {
computer.setRam(ram);
}
@Override
public void buildStorage(String storage) {
computer.setStorage(storage);
}
@Override
public Computer getResult() {
return computer;
}
}
// 步骤4:定义指挥者(Director,可选)
public class Director {
private ComputerBuilder builder;
public Director(ComputerBuilder builder) {
this.builder = builder;
}
// 定义标准组装流程
public void constructBasicComputer() {
builder.buildCPU("Intel i5");
builder.buildRAM("8GB DDR4");
builder.buildStorage("512GB SSD");
}
public void constructHighEndComputer() {
builder.buildCPU("AMD Ryzen 9");
builder.buildRAM("32GB DDR5");
builder.buildStorage("2TB NVMe SSD");
}
}
// 步骤5:客户端使用
public class Client {
public static void main(String[] args) {
// 创建生成器
ComputerBuilder builder = new StandardComputerBuilder();
// 使用指挥者(可选)
Director director = new Director(builder);
director.constructBasicComputer();
// 直接通过生成器构建(无指挥者)
// builder.buildCPU("Intel i5");
// builder.buildRAM("8GB DDR4");
// builder.buildStorage("512GB SSD");
// 获取最终产品
Computer computer = builder.getResult();
System.out.println(computer); // 输出:Computer [CPU=Intel i5, RAM=8GB DDR4, Storage=512GB SSD]
}
}
生成器模式的变体:链式生成器(Fluent Builder)
通过返回 this 实现链式调用,提升代码可读性:
public class Computer {
private String cpu;
private String ram;
private String storage;
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.ram = builder.ram;
this.storage = builder.storage;
}
public static class Builder {
private String cpu;
private String ram;
private String storage;
public Builder cpu(String cpu) {
this.cpu = cpu;
return this;
}
public Builder ram(String ram) {
this.ram = ram;
return this;
}
public Builder storage(String storage) {
this.storage = storage;
return this;
}
public Computer build() {
return new Computer(this);
}
}
}
// 使用方式
Computer computer = new Computer.Builder()
.cpu("Intel i7")
.ram("16GB DDR4")
.storage("1TB NVMe SSD")
.build();
应用场景
生成器模式适用于以下场景:
- 多参数对象构建:对象需要多个可选参数(如订单、用户配置)。
- 复杂构建流程:对象构建涉及多个步骤(如生成PDF报告需设置页眉、正文、页脚)。
- 避免重叠构造函数:替代多个重载的构造函数(如 new User(name, age, email, phone))。
- 构建不可变对象:通过生成器逐步设置参数后,返回不可变对象(如Java中的StringBuilder生成String)。
优缺点分析
| 优点 | 缺点 |
|---|---|
| 解耦构建过程与产品表示 | 增加代码复杂度(需定义生成器类) |
| 支持分步骤构建和灵活配置 | 对简单对象可能过度设计 |
| 提高代码可读性和可维护性 |
生成器模式 vs 工厂模式
| 维度 | 生成器模式 | 工厂模式 |
|---|---|---|
| 核心目标 | 分步骤构建复杂对象 | 创建单一对象 |
| 适用场景 | 多参数、多步骤的对象构建 | 直接创建完整对象 |
| 代码复杂度 | 高(需定义生成器类) | 低(直接调用工厂方法) |
| 典型应用 | StringBuilder、文档生成器 | Calendar.getInstance()、Spring Bean |
总结
生成器模式通过将复杂对象的构建过程分解为独立的步骤,提供了高度灵活性和可维护性。其核心价值在于:
-
代码清晰:避免冗长的构造函数参数列表。
-
灵活扩展:支持逐步构建和不同产品表示。
-
解耦构建逻辑:分离构建过程与产品实现。
适用建议:
-
当对象需要多个可选参数或构建步骤时,优先选择生成器模式。
-
对于简单对象,直接使用构造函数或工厂方法即可。
原型模式
定义
原型模式(Prototype Pattern) 是一种创建型设计模式,通过复制现有对象(原型)来创建新对象,而无需依赖子类或构造方法。其核心思想是以现有实例为模板,通过克隆机制生成新对象,适用于对象创建成本高或需动态配置对象的场景。
核心思想
- 克隆代替构造:避免重复初始化复杂对象,直接基于已有对象复制生成新实例。
- 动态扩展:允许运行时动态添加或修改对象的属性。
- 性能优化:减少资源消耗(如数据库查询、复杂计算)。
模式结构
| 角色 | 说明 |
|---|---|
| 原型接口(Prototype) | 定义克隆方法(如 clone()),通常实现 Cloneable 接口(Java)。 |
| 具体原型类(ConcretePrototype) | 实现克隆方法的具体类,决定浅拷贝或深拷贝。 |
| 客户端(Client) | 通过调用原型对象的克隆方法创建新对象。 |
classDiagram
class Prototype {
<<interface>>
+clone(): Prototype
}
class ConcretePrototype {
-field1: String
-field2: Integer
+clone(): Prototype
+setField1(String)
+getField1(): String
}
class Client {
-prototype: Prototype
+operation()
}
Prototype <|.. ConcretePrototype : 实现
Client --> Prototype : 使用
代码示例
以“图形编辑器”为例,实现圆形(Circle)和矩形(Rectangle)的原型克隆:
// 1. 原型接口(实现 Cloneable)
interface Shape extends Cloneable {
Shape clone();
void draw();
}
// 2. 具体原型类:圆形
class Circle implements Shape {
private String color;
private int radius;
public Circle(String color, int radius) {
this.color = color;
this.radius = radius;
}
@Override
public Shape clone() {
try {
return (Circle) super.clone(); // 浅拷贝(引用类型需手动处理)
} catch (CloneNotSupportedException e) {
return null;
}
}
@Override
public void draw() {
System.out.println("绘制圆形:颜色=" + color + ", 半径=" + radius);
}
public void setColor(String color) {
this.color = color;
}
}
// 3. 具体原型类:矩形(深拷贝示例)
class Rectangle implements Shape {
private String color;
private int width;
private int height;
private Dimensions dimensions; // 引用类型字段
public Rectangle(String color, int width, int height, Dimensions dimensions) {
this.color = color;
this.width = width;
this.height = height;
this.dimensions = dimensions;
}
@Override
public Shape clone() {
// 深拷贝:手动复制引用类型字段
Rectangle cloned = new Rectangle(color, width, height, dimensions.clone());
return cloned;
}
@Override
public void draw() {
System.out.println("绘制矩形:颜色=" + color + ", 尺寸=" + width + "x" + height
+ ", 单位=" + dimensions.getUnit());
}
}
// 引用类型辅助类(需实现克隆)
class Dimensions implements Cloneable {
private String unit;
public Dimensions(String unit) {
this.unit = unit;
}
public String getUnit() {
return unit;
}
@Override
public Dimensions clone() {
try {
return (Dimensions) super.clone(); // 浅拷贝(若嵌套对象需递归处理)
} catch (CloneNotSupportedException e) {
return null;
}
}
}
// 4. 客户端使用
public class Client {
public static void main(String[] args) {
// 创建原型对象
Shape redCircle = new Circle("红色", 10);
Shape blueRectangle = new Rectangle("蓝色", 20, 30, new Dimensions("厘米"));
// 克隆对象并修改属性
Shape clonedCircle = redCircle.clone();
((Circle) clonedCircle).setColor("绿色");
Shape clonedRectangle = blueRectangle.clone();
// 绘制图形
redCircle.draw(); // 输出:绘制圆形:颜色=红色, 半径=10
clonedCircle.draw(); // 输出:绘制圆形:颜色=绿色, 半径=10
clonedRectangle.draw(); // 输出:绘制矩形:颜色=蓝色, 尺寸=20x30, 单位=厘米
}
}
应用场景
复杂对象初始化:对象创建需大量资源(如数据库连接、文件IO),通过克隆复用已有实例。
动态配置对象:运行时根据用户配置生成不同变体的对象(如游戏中的角色属性模板)。
撤销/重做功能:保存对象历史状态快照(如文档编辑器的撤销栈)。
优缺点
| 优点 | 缺点 |
|---|---|
| 避免重复初始化复杂对象 | 深拷贝实现复杂(需递归处理) |
| 动态生成对象变体 | 需注意循环引用的处理 |
| 提升性能(减少资源消耗) | 可能破坏封装性(访问私有字段) |
与其他模式对比
| 模式 | 核心区别 |
|---|---|
| 工厂模式 | 通过子类创建对象,原型模式直接复制现有对象。 |
| 单例模式 | 单例限制实例数量,原型模式生成多个克隆。 |
| 备忘录模式 | 备忘录保存状态,原型复制整个对象。 |
最佳实践
优先使用深拷贝:避免引用共享导致意外修改(如 Rectangle 中的 Dimensions 字段)。
实现标记接口:Java 中通过 Cloneable 接口标识可克隆对象,但需手动实现 clone()。
结合工厂模式:使用原型管理器(注册表)存储常用原型,按需克隆。
实际案例
Java 的 Object.clone():基础克隆机制,需结合 Cloneable 接口使用。
Spring 的 Bean 作用域:原型作用域的 Bean 每次请求生成新实例(通过克隆配置好的原型 Bean)。
游戏开发中的敌人生成:克隆预配置的敌人模板,动态调整属性(如血量、攻击力)。
总结
原型模式通过克隆机制高效生成对象,尤其适用于复杂对象初始化和动态配置场景。其核心在于合理选择浅拷贝或深拷贝,并确保克隆过程不破坏对象完整性。结合工厂模式或注册表管理,可进一步提升系统的灵活性和可维护性。
单例模式详解
1. 定义
单例模式(Singleton Pattern)是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。它常用于管理共享资源(如配置、日志记录器、数据库连接池),避免重复创建对象带来的开销或不一致性。
2. 核心思想
- 唯一性:类只能有一个实例。
- 全局访问:通过静态方法提供全局访问入口。
- 延迟初始化(可选):实例在第一次使用时创建,而非类加载时。
3. 类图(Mermaid)
classDiagram
class Singleton {
-static instance: Singleton
-Singleton() // 私有构造方法
+static getInstance(): Singleton
+someBusinessMethod() void
}
说明:
- 私有构造方法:禁止外部通过
new创建实例。 - 静态实例变量:保存唯一实例。
- 静态方法
getInstance():全局访问入口。
4. 常见实现方式
4.1 饿汉式(Eager Initialization)
特点:类加载时立即初始化实例,线程安全但可能浪费资源。
public class EagerSingleton {
// 类加载时直接初始化实例
private static final EagerSingleton instance = new EagerSingleton();
// 私有构造方法
private EagerSingleton() {}
// 全局访问点
public static EagerSingleton getInstance() {
return instance;
}
}
优点:实现简单,线程安全。
缺点:实例提前创建,若未使用则浪费内存。
4.2 懒汉式(Lazy Initialization)
特点:延迟实例化,但需解决线程安全问题。
4.2.1 非线程安全版
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
// 非线程安全:多线程可能创建多个实例
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
4.2.2 线程安全版(同步方法)
public class ThreadSafeLazySingleton {
private static ThreadSafeLazySingleton instance;
private ThreadSafeLazySingleton() {}
// 同步方法保证线程安全,但性能较低
public static synchronized ThreadSafeLazySingleton getInstance() {
if (instance == null) {
instance = new ThreadSafeLazySingleton();
}
return instance;
}
}
缺点:同步锁导致性能下降。
4.3 双重检查锁(Double-Checked Locking)
特点:减少同步代码块,兼顾线程安全与性能。
public class DCLSingleton {
// volatile 防止指令重排序
private static volatile DCLSingleton instance;
private DCLSingleton() {}
public static DCLSingleton getInstance() {
if (instance == null) { // 第一次检查
synchronized (DCLSingleton.class) { // 加锁
if (instance == null) { // 第二次检查
instance = new DCLSingleton();
}
}
}
return instance;
}
}
优点:线程安全且性能较高。
关键点:volatile 防止 JVM 指令重排序导致的未完全初始化问题。
4.4 静态内部类(Static Inner Class)
特点:利用类加载机制保证线程安全,且延迟初始化。
public class InnerClassSingleton {
private InnerClassSingleton() {}
// 静态内部类持有实例
private static class SingletonHolder {
private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
}
public static InnerClassSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
原理:内部类 SingletonHolder 在首次调用 getInstance() 时加载,实现延迟初始化且线程安全。
4.5 枚举(Enum)
特点:简洁、线程安全,且天然防止反射和序列化破坏单例。
public enum EnumSingleton {
INSTANCE; // 单例实例
public void someMethod() {
// 业务逻辑
}
}
// 使用示例
EnumSingleton instance = EnumSingleton.INSTANCE;
优点:
- 无需考虑反射攻击(枚举类无法通过反射创建实例)。
- 序列化自动处理,不会生成新对象。
5. 防止破坏单例
5.1 反射攻击
通过反射调用私有构造方法可破坏单例。
防御方法:在构造方法中抛出异常。
private Singleton() {
if (instance != null) {
throw new RuntimeException("禁止反射创建实例!");
}
}
5.2 序列化攻击
反序列化可能生成新实例。
防御方法:实现 readResolve() 方法。
protected Object readResolve() {
return getInstance();
}
6. 应用场景
- 配置管理:全局唯一的配置对象。
- 日志记录器:统一管理日志输出。
- 数据库连接池:避免频繁创建连接。
- 缓存系统:统一管理缓存数据。
7. 总结
| 实现方式 | 线程安全 | 延迟初始化 | 防反射 | 防序列化 |
|---|---|---|---|---|
| 饿汉式 | ✔️ | ❌ | ❌ | ❌ |
| 懒汉式(同步方法) | ✔️ | ✔️ | ❌ | ❌ |
| 双重检查锁 | ✔️ | ✔️ | ❌ | ❌ |
| 静态内部类 | ✔️ | ✔️ | ❌ | ❌ |
| 枚举 | ✔️ | ❌ | ✔️ | ✔️ |
推荐选择:
- 简单场景 → 饿汉式
- 高并发场景 → 双重检查锁 或 静态内部类
- 绝对安全场景 → 枚举
单例模式通过严格控制实例数量,确保全局一致性,是管理共享资源的首选方案。
后续内容更新中,请耐心等待