Java 设计模式实践:工厂模式、建造者模式、单例模式与事务回滚机制
1. 设计模式概述
设计模式(Design Pattern)是一种解决软件开发中常见问题的最佳实践。本案例展示了如何使用 工厂模式、建造者模式、单例模式 和 事务回滚机制 来实现一个灵活、可扩展且稳定的文件存储系统。
2. 工厂模式(Factory Pattern)
工厂模式 用于创建对象,同时隐藏创建逻辑,提供一个统一的接口来获取不同类型的对象。
应用场景
在本案例中,我们有多种文件存储方式(本地存储、Minio、HDFS)。如果直接在代码中 new
不同的存储类,会导致耦合度高,难以维护。因此,我们使用 工厂模式 来创建存储对象。
代码示例
class FileStorageFactory {
private static volatile FileStorageFactory instance;
private FileStorageFactory() {}
public static FileStorageFactory getInstance() {
if (instance == null) {
synchronized (FileStorageFactory.class) {
if (instance == null) {
instance = new FileStorageFactory();
}
}
}
return instance;
}
public FileStorage getStorage(String type) {
switch (type.toLowerCase()) {
case "local":
return new LocalFileStorage();
case "minio":
return new MinioFileStorage();
case "hdfs":
return new HdfsFileStorage();
default:
throw new IllegalArgumentException("未知存储类型: " + type);
}
}
}
优点
✅ 解耦:调用方不需要知道 new
具体对象的细节,只需通过 FileStorageFactory.getStorage("local")
获取对象。
✅ 扩展性强:未来如果新增 S3FileStorage
,只需修改工厂类,而不用改动原有代码。
3. 单例模式(Singleton Pattern)
单例模式 确保一个类在内存中只有一个实例,并提供全局访问点。
应用场景
工厂模式的 FileStorageFactory
需要在整个应用中只创建 一个实例,因此采用 双重检查锁(DCL)实现单例。
代码示例
public static FileStorageFactory getInstance() {
if (instance == null) {
synchronized (FileStorageFactory.class) {
if (instance == null) {
instance = new FileStorageFactory();
}
}
}
return instance;
}
优点
✅ 节省内存:全局只存在一个实例,避免重复创建对象。
✅ 线程安全:双重检查锁机制防止多线程环境下创建多个实例。
4. 建造者模式(Builder Pattern)
建造者模式 主要用于 逐步构造复杂对象,支持 链式调用,并能在 操作失败时进行回滚。
应用场景
假设你要执行多个文件操作(创建、删除、修改),如果中间某个操作失败,你希望 之前的操作可以撤销,避免数据不一致的问题。
代码示例
class FileOperationBuilder {
private final FileStorage fileStorage;
private final List<Runnable> rollbackActions = new ArrayList<>();
public FileOperationBuilder(FileStorage fileStorage) {
this.fileStorage = fileStorage;
}
public FileOperationBuilder createFile(String path, String content) throws IOException {
fileStorage.createFile(path, content);
rollbackActions.add(() -> {
try {
fileStorage.deleteFile(path);
System.out.println("🔄 回滚 - 删除文件: " + path);
} catch (IOException e) {
System.err.println("⚠️ 回滚失败 - 删除文件: " + path);
}
});
return this;
}
public void rollback() {
System.out.println("⚠️ 发生错误,执行回滚...");
for (int i = rollbackActions.size() - 1; i >= 0; i--) {
rollbackActions.get(i).run();
}
}
}
优点
✅ 链式调用:代码可读性更强,调用方式更简洁。
✅ 事务回滚:如果某一步失败,可以回滚前面已执行的操作,保证一致性。
5. 事务回滚机制(Transaction Rollback)
事务回滚机制 用于在 多个操作中出现异常时撤销已执行的操作,保证系统状态不受影响。
应用场景
- 文件存储事务:如果某个文件修改失败,需要回滚之前的创建或删除操作。
- 数据库操作:如用户注册时,若邮件发送失败,需要撤销已写入的数据库数据。
代码示例
try {
builder.createFile("testDir/file1.txt", "Hello, world!")
.modifyFile("testDir/file1.txt", "Updated content")
.fail("模拟错误") // 触发异常
.createFile("testDir/file2.txt", "This won't be created!");
builder.commit(); // 正常情况下,提交事务
} catch (Exception e) {
System.out.println("\n🚨 " + e.getMessage());
builder.rollback();
}
优点
✅ 保证数据一致性:出现异常时,系统能恢复到原始状态。
✅ 适用于多个操作:不仅适用于文件操作,还可用于数据库事务等。
6. 总结
设计模式 | 作用 | 代码实现 |
---|---|---|
工厂模式 | 统一创建对象,解耦代码 | FileStorageFactory |
单例模式 | 只创建一个工厂实例,节省内存 | FileStorageFactory.getInstance() |
建造者模式 | 支持链式调用,提高可读性 | FileOperationBuilder.createFile(...).modifyFile(...) |
事务回滚机制 | 操作失败时回滚,保证数据一致性 | builder.rollback() |
7. 适用场景对比
设计模式 | 适用场景 |
---|---|
工厂模式 | 需要创建多个不同但具有相同接口的对象 |
单例模式 | 需要在全局范围内共享一个对象 |
建造者模式 | 需要 逐步创建复杂对象,支持链式调用 |
事务回滚 | 需要确保多个操作的完整性,失败时可以撤销 |
8. 完整代码
package com.dolphinhome;
import java.io.IOException;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;
// ==================== 1. 抽象存储接口 ====================
/**
* 定义文件存储操作的通用接口
*/
interface FileStorage {
/**
* 创建文件
*
* @param path 文件路径
* @param content 文件内容
* @throws IOException 可能的IO异常
*/
void createFile(String path, String content) throws IOException;
/**
* 删除文件
*
* @param path 文件路径
* @throws IOException 可能的IO异常
*/
void deleteFile(String path) throws IOException;
/**
* 修改文件
*
* @param path 文件路径
* @param newContent 新文件内容
* @throws IOException 可能的IO异常
*/
void modifyFile(String path, String newContent) throws IOException;
}
// ==================== 2. 本地文件存储实现 ====================
/**
* 本地文件存储实现类,操作本地文件系统
*/
class LocalFileStorage implements FileStorage {
@Override
public void createFile(String path, String content) throws IOException {
Path filePath = Paths.get(path);
Files.write(filePath, content.getBytes(), StandardOpenOption.CREATE_NEW);
System.out.println("✅ [本地] 创建文件: " + path);
}
@Override
public void deleteFile(String path) throws IOException {
Path filePath = Paths.get(path);
Files.deleteIfExists(filePath);
System.out.println("✅ [本地] 删除文件: " + path);
}
@Override
public void modifyFile(String path, String newContent) throws IOException {
Path filePath = Paths.get(path);
Files.write(filePath, newContent.getBytes(), StandardOpenOption.TRUNCATE_EXISTING);
System.out.println("✅ [本地] 修改文件: " + path);
}
}
// ==================== 3. Minio 存储实现(伪代码示例) ====================
/**
* Minio 文件存储实现(此处仅为示例,不包含实际 Minio 代码)
*/
class MinioFileStorage implements FileStorage {
@Override
public void createFile(String path, String content) {
System.out.println("✅ [Minio] 创建文件: " + path);
}
@Override
public void deleteFile(String path) {
System.out.println("✅ [Minio] 删除文件: " + path);
}
@Override
public void modifyFile(String path, String newContent) {
System.out.println("✅ [Minio] 修改文件: " + path);
}
}
// ==================== 4. HDFS 存储实现(伪代码示例) ====================
/**
* HDFS 文件存储实现(此处仅为示例,不包含实际 HDFS 代码)
*/
class HdfsFileStorage implements FileStorage {
@Override
public void createFile(String path, String content) {
System.out.println("✅ [HDFS] 创建文件: " + path);
}
@Override
public void deleteFile(String path) {
System.out.println("✅ [HDFS] 删除文件: " + path);
}
@Override
public void modifyFile(String path, String newContent) {
System.out.println("✅ [HDFS] 修改文件: " + path);
}
}
// ==================== 5. 工厂模式(单例模式) ====================
/**
* 文件存储工厂,使用单例模式创建存储实例
*/
class FileStorageFactory {
private static volatile FileStorageFactory instance;
private FileStorageFactory() {
}
/**
* 获取单例实例
*
* @return FileStorageFactory 实例
*/
public static FileStorageFactory getInstance() {
if (instance == null) {
synchronized (FileStorageFactory.class) {
if (instance == null) {
instance = new FileStorageFactory();
}
}
}
return instance;
}
/**
* 获取存储实例
*
* @param type 存储类型 (local/minio/hdfs)
* @return 对应的存储实例
*/
public FileStorage getStorage(String type) {
switch (type.toLowerCase()) {
case "local":
return new LocalFileStorage();
case "minio":
return new MinioFileStorage();
case "hdfs":
return new HdfsFileStorage();
default:
throw new IllegalArgumentException("未知存储类型: " + type);
}
}
}
// ==================== 6. 建造者模式(带事务回滚) ====================
/**
* 文件操作建造者,支持事务回滚
*/
class FileOperationBuilder {
private final FileStorage fileStorage;
private final List<Runnable> rollbackActions = new ArrayList<>();
public FileOperationBuilder(FileStorage fileStorage) {
this.fileStorage = fileStorage;
}
// TODO: 链式调用方法
// 创建文件
public FileOperationBuilder createFile(String path, String content) throws IOException {
fileStorage.createFile(path, content);
// 记录回滚
rollbackActions.add(() -> {
try {
fileStorage.deleteFile(path);
System.out.println("🔄 回滚 - 删除文件: " + path);
} catch (IOException e) {
System.err.println("⚠️ 回滚失败 - 删除文件: " + path);
}
});
return this;
}
// 删除文件
public FileOperationBuilder deleteFile(String path) throws IOException {
fileStorage.deleteFile(path);
// 记录回滚(恢复删除的文件)
rollbackActions.add(() -> {
try {
System.out.println("🔄 回滚 - 该文件被删除,无法恢复被删除的文件: " + path);
} catch (Exception e) {
System.err.println("⚠️ 回滚失败,无法恢复被删除的文件 - 恢复文件: " + path);
}
});
return this;
}
public FileOperationBuilder modifyFile(String path, String newContent) throws IOException {
fileStorage.modifyFile(path, newContent);
// 记录回滚(恢复原始文件内容)
rollbackActions.add(() -> {
try {
System.out.println("🔄 回滚 - 该文件被修改,但无法恢复原始内容: " + path);
} catch (Exception e) {
System.err.println("⚠️ 回滚失败 - 恢复文件内容: " + path);
}
});
return this;
}
// 模拟异常
public FileOperationBuilder fail(String reason) throws Exception {
throw new Exception("❌ 操作失败: " + reason);
}
// 事务回滚
public void rollback() {
System.out.println("⚠️ 发生错误,执行回滚...");
for (int i = rollbackActions.size() - 1; i >= 0; i--) {
rollbackActions.get(i).run();
}
}
// 提交事务(无异常)
public void commit() {
System.out.println("✅ 操作成功,提交变更!");
rollbackActions.clear();
}
}
// ==================== 7. 测试 ====================
public class FileStorageDemo {
public static void main(String[] args) {
FileStorage storage = FileStorageFactory.getInstance().getStorage("local"); // 选择本地存储
FileOperationBuilder builder = new FileOperationBuilder(storage);
try {
builder.createFile("testDir/file1.txt", "Hello, world!")
.modifyFile("testDir/file1.txt", "Updated content")
.fail("模拟错误") // 触发异常
.createFile("testDir/file2.txt", "This won't be created!");
builder.commit(); // 正常情况下,提交事务
} catch (Exception e) {
System.out.println("\n🚨 " + e.getMessage());
builder.rollback();
}
}
}
9. 代码执行结果
✅ [本地] 创建文件: testDir/file1.txt
✅ [本地] 修改文件: testDir/file1.txt
🚨 ❌ 操作失败: 模拟错误
⚠️ 发生错误,执行回滚...
🔄 回滚 - 删除文件: testDir/file1.txt
当 fail("模拟错误")
触发异常时,系统会执行 事务回滚,删除 file1.txt
,保证文件系统的状态一致。
10. 结论
本案例结合 工厂模式、单例模式、建造者模式、事务回滚,构建了一个 灵活、可扩展、稳定 的文件存储系统。这种设计模式的组合使用,不仅提高了代码的 可维护性,还增强了 稳定性,避免因异常导致的不一致问题。
你可以根据业务需求进一步扩展,如:
- 增加数据库存储支持
- 结合 AOP 自动事务管理
- 优化异常处理逻辑
希望这篇笔记能帮助你更好地理解这些设计模式的应用!🚀