Java工厂模式原理详解
工厂模式是Java中最常用的设计模式之一,它属于创建型模式,主要解决对象创建的问题,将对象的创建与使用分离,提高代码的灵活性和可维护性。
一、工厂模式概述
为什么需要工厂模式?
没有工厂模式的问题:
// 客户端直接创建具体对象 - 紧耦合
public class Client {
public void process() {
// 直接依赖具体实现类
Car car = new BenzCar(); // 如果要换车型,需要修改代码
car.drive();
// 或者
Car car2 = new BMWCar(); // 还是需要修改代码
car2.drive();
}
}
工厂模式的优势:
-
解耦:客户端不关心对象的创建细节
-
可扩展:新增产品类型时不需要修改客户端代码
-
统一管理:集中管理对象的创建逻辑
-
符合开闭原则:对扩展开放,对修改关闭
二、简单工厂模式(静态工厂模式)
1. 基本结构
客户端 → 工厂类 → 具体产品
2. 代码实现
// 1. 产品接口
public interface Car {
void drive();
String getInfo();
}
// 2. 具体产品实现
public class BenzCar implements Car {
@Override
public void drive() {
System.out.println("奔驰车在行驶...");
}
@Override
public String getInfo() {
return "奔驰汽车";
}
}
public class BMWCar implements Car {
@Override
public void drive() {
System.out.println("宝马车在行驶...");
}
@Override
public String getInfo() {
return "宝马汽车";
}
}
public class AudiCar implements Car {
@Override
public void drive() {
System.out.println("奥迪车在行驶...");
}
@Override
public String getInfo() {
return "奥迪汽车";
}
}
// 3. 简单工厂类
public class SimpleCarFactory {
/**
* 静态工厂方法 - 根据类型创建对象
*/
public static Car createCar(String type) {
if (type == null) {
return null;
}
switch (type.toLowerCase()) {
case "benz":
return new BenzCar();
case "bmw":
return new BMWCar();
case "audi":
return new AudiCar();
default:
throw new IllegalArgumentException("不支持的汽车类型: " + type);
}
}
/**
* 方法重载 - 根据枚举创建对象
*/
public static Car createCar(CarType carType) {
if (carType == null) {
return null;
}
switch (carType) {
case BENZ:
return new BenzCar();
case BMW:
return new BMWCar();
case AUDI:
return new AudiCar();
default:
throw new IllegalArgumentException("不支持的汽车类型: " + carType);
}
}
}
// 汽车类型枚举
public enum CarType {
BENZ, BMW, AUDI
}
// 4. 客户端使用
public class Client {
public static void main(String[] args) {
// 使用简单工厂创建对象
Car benz = SimpleCarFactory.createCar("benz");
Car bmw = SimpleCarFactory.createCar(CarType.BMW);
benz.drive(); // 输出: 奔驰车在行驶...
bmw.drive(); // 输出: 宝马车在行驶...
System.out.println(benz.getInfo()); // 输出: 奔驰汽车
System.out.println(bmw.getInfo()); // 输出: 宝马汽车
}
}
3. 优缺点分析
优点:
-
客户端与具体实现解耦
-
代码结构清晰
缺点:
-
违反开闭原则(新增产品需要修改工厂类)
-
工厂类职责过重
三、工厂方法模式(Factory Method Pattern)
1. 核心思想
定义一个创建对象的接口,但让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
2. 类图结构
抽象创建者(Creator)
↑
具体创建者(Concrete Creator) → 具体产品(Concrete Product)
3. 代码实现
// 1. 产品接口
public interface Logger {
void log(String message);
void error(String message);
void warn(String message);
}
// 2. 具体产品
public class FileLogger implements Logger {
@Override
public void log(String message) {
System.out.println("文件日志 - INFO: " + message);
}
@Override
public void error(String message) {
System.out.println("文件日志 - ERROR: " + message);
}
@Override
public void warn(String message) {
System.out.println("文件日志 - WARN: " + message);
}
}
public class DatabaseLogger implements Logger {
@Override
public void log(String message) {
System.out.println("数据库日志 - INFO: " + message);
}
@Override
public void error(String message) {
System.out.println("数据库日志 - ERROR: " + message);
}
@Override
public void warn(String message) {
System.out.println("数据库日志 - WARN: " + message);
}
}
public class ConsoleLogger implements Logger {
@Override
public void log(String message) {
System.out.println("控制台日志 - INFO: " + message);
}
@Override
public void error(String message) {
System.out.println("控制台日志 - ERROR: " + message);
}
@Override
public void warn(String message) {
System.out.println("控制台日志 - WARN: " + message);
}
}
// 3. 抽象创建者
public abstract class LoggerFactory {
/**
* 工厂方法 - 由子类实现具体创建逻辑
*/
public abstract Logger createLogger();
/**
* 业务方法 - 使用工厂方法创建的产品
*/
public void log(String message) {
Logger logger = createLogger();
logger.log(message);
}
public void error(String message) {
Logger logger = createLogger();
logger.error(message);
}
}
// 4. 具体创建者
public class FileLoggerFactory extends LoggerFactory {
@Override
public Logger createLogger() {
// 可以在这里进行复杂的初始化操作
System.out.println("创建文件日志记录器...");
return new FileLogger();
}
}
public class DatabaseLoggerFactory extends LoggerFactory {
@Override
public Logger createLogger() {
System.out.println("创建数据库日志记录器...");
return new DatabaseLogger();
}
}
public class ConsoleLoggerFactory extends LoggerFactory {
@Override
public Logger createLogger() {
System.out.println("创建控制台日志记录器...");
return new ConsoleLogger();
}
}
// 5. 客户端使用
public class LoggerClient {
public static void main(String[] args) {
// 使用文件日志
LoggerFactory fileFactory = new FileLoggerFactory();
fileFactory.log("这是一个信息日志");
fileFactory.error("这是一个错误日志");
// 使用数据库日志
LoggerFactory dbFactory = new DatabaseLoggerFactory();
dbFactory.log("数据库操作日志");
// 使用控制台日志
LoggerFactory consoleFactory = new ConsoleLoggerFactory();
consoleFactory.warn("这是一个警告");
}
}
4. 带参数的工厂方法
// 增强的工厂方法
public abstract class EnhancedLoggerFactory {
/**
* 带参数的工厂方法
*/
public abstract Logger createLogger(LoggerConfig config);
/**
* 重载的工厂方法
*/
public Logger createLogger() {
return createLogger(LoggerConfig.defaultConfig());
}
}
// 配置类
public class LoggerConfig {
private String level;
private String format;
private String filePath;
public LoggerConfig(String level, String format, String filePath) {
this.level = level;
this.format = format;
this.filePath = filePath;
}
public static LoggerConfig defaultConfig() {
return new LoggerConfig("INFO", "TEXT", "logs/app.log");
}
// getters and setters
}
// 具体实现
public class ConfigurableFileLoggerFactory extends EnhancedLoggerFactory {
@Override
public Logger createLogger(LoggerConfig config) {
FileLogger logger = new FileLogger();
// 根据配置初始化logger
System.out.println("使用配置创建文件日志: " + config.getFilePath());
return logger;
}
}
5. 工厂方法模式的优缺点
优点:
-
完全符合开闭原则
-
客户端与具体产品解耦
-
易于扩展新的产品族
缺点:
-
类的数量增加
-
增加了系统的复杂性
四、抽象工厂模式(Abstract Factory Pattern)
1. 核心思想
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
2. 适用场景
-
系统需要一系列相互关联的产品
-
系统需要动态切换产品族
-
产品等级结构稳定,但产品族经常变化
3. 代码实现:跨平台UI组件
// 1. 抽象产品族 - UI组件
public interface Button {
void render();
void onClick();
}
public interface TextField {
void render();
String getText();
void setText(String text);
}
public interface Checkbox {
void render();
boolean isChecked();
void setChecked(boolean checked);
}
// 2. 具体产品 - Windows风格
public class WindowsButton implements Button {
@Override
public void render() {
System.out.println("渲染Windows风格按钮");
}
@Override
public void onClick() {
System.out.println("Windows按钮被点击");
}
}
public class WindowsTextField implements TextField {
private String text = "";
@Override
public void render() {
System.out.println("渲染Windows风格文本框");
}
@Override
public String getText() {
return text;
}
@Override
public void setText(String text) {
this.text = text;
}
}
public class WindowsCheckbox implements Checkbox {
private boolean checked = false;
@Override
public void render() {
System.out.println("渲染Windows风格复选框: " + (checked ? "✓" : "□"));
}
@Override
public boolean isChecked() {
return checked;
}
@Override
public void setChecked(boolean checked) {
this.checked = checked;
}
}
// 3. 具体产品 - Mac风格
public class MacButton implements Button {
@Override
public void render() {
System.out.println("渲染Mac风格按钮");
}
@Override
public void onClick() {
System.out.println("Mac按钮被点击");
}
}
public class MacTextField implements TextField {
private String text = "";
@Override
public void render() {
System.out.println("渲染Mac风格文本框");
}
@Override
public String getText() {
return text;
}
@Override
public void setText(String text) {
this.text = text;
}
}
public class MacCheckbox implements Checkbox {
private boolean checked = false;
@Override
public void render() {
System.out.println("渲染Mac风格复选框: " + (checked ? "✓" : "□"));
}
@Override
public boolean isChecked() {
return checked;
}
@Override
public void setChecked(boolean checked) {
this.checked = checked;
}
}
// 4. 抽象工厂
public interface GUIFactory {
Button createButton();
TextField createTextField();
Checkbox createCheckbox();
}
// 5. 具体工厂
public class WindowsFactory implements GUIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public TextField createTextField() {
return new WindowsTextField();
}
@Override
public Checkbox createCheckbox() {
return new WindowsCheckbox();
}
}
public class MacFactory implements GUIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public TextField createTextField() {
return new MacTextField();
}
@Override
public Checkbox createCheckbox() {
return new MacCheckbox();
}
}
// 6. 客户端代码
public class Application {
private Button button;
private TextField textField;
private Checkbox checkbox;
private GUIFactory factory;
public Application(GUIFactory factory) {
this.factory = factory;
createUI();
}
private void createUI() {
this.button = factory.createButton();
this.textField = factory.createTextField();
this.checkbox = factory.createCheckbox();
}
public void render() {
System.out.println("=== 渲染UI界面 ===");
button.render();
textField.render();
checkbox.render();
}
public void simulateUserAction() {
System.out.println("\n=== 模拟用户操作 ===");
button.onClick();
textField.setText("Hello World");
checkbox.setChecked(true);
checkbox.render();
}
}
// 7. 配置类 - 根据环境选择工厂
public class FactoryConfig {
public static GUIFactory createFactory() {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
return new WindowsFactory();
} else if (os.contains("mac")) {
return new MacFactory();
} else {
throw new UnsupportedOperationException("不支持的操作系统: " + os);
}
}
}
// 8. 客户端使用
public class AbstractFactoryClient {
public static void main(String[] args) {
// 根据当前操作系统自动选择工厂
GUIFactory factory = FactoryConfig.createFactory();
Application app = new Application(factory);
app.render();
app.simulateUserAction();
// 手动指定工厂
System.out.println("\n=== 测试Mac风格 ===");
Application macApp = new Application(new MacFactory());
macApp.render();
}
}
4. 抽象工厂扩展:新增产品族
// 新增Linux风格产品族
public class LinuxButton implements Button {
@Override
public void render() {
System.out.println("渲染Linux风格按钮");
}
@Override
public void onClick() {
System.out.println("Linux按钮被点击");
}
}
public class LinuxTextField implements TextField {
private String text = "";
@Override
public void render() {
System.out.println("渲染Linux风格文本框");
}
@Override
public String getText() {
return text;
}
@Override
public void setText(String text) {
this.text = text;
}
}
public class LinuxCheckbox implements Checkbox {
private boolean checked = false;
@Override
public void render() {
System.out.println("渲染Linux风格复选框: " + (checked ? "✓" : "□"));
}
@Override
public boolean isChecked() {
return checked;
}
@Override
public void setChecked(boolean checked) {
this.checked = checked;
}
}
public class LinuxFactory implements GUIFactory {
@Override
public Button createButton() {
return new LinuxButton();
}
@Override
public TextField createTextField() {
return new LinuxTextField();
}
@Override
public Checkbox createCheckbox() {
return new LinuxCheckbox();
}
}
// 更新配置类
public class EnhancedFactoryConfig {
public static GUIFactory createFactory(String style) {
if (style == null) {
// 默认根据操作系统
String os = System.getProperty("os.name").toLowerCase();
style = os.contains("win") ? "windows" :
os.contains("mac") ? "mac" : "linux";
}
switch (style.toLowerCase()) {
case "windows":
return new WindowsFactory();
case "mac":
return new MacFactory();
case "linux":
return new LinuxFactory();
default:
throw new IllegalArgumentException("不支持的样式: " + style);
}
}
}
五、工厂模式在JDK和框架中的应用
1. JDK中的工厂模式
// Calendar类的工厂方法
public class JDKFactoryExample {
public static void main(String[] args) {
// 工厂方法模式
Calendar calendar = Calendar.getInstance(); // 根据时区返回具体实例
Calendar chinaCalendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
// 简单工厂模式
NumberFormat currencyFormat = NumberFormat.getCurrencyInstance(Locale.CHINA);
NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US);
}
}
2. Spring框架中的工厂模式
// BeanFactory - 工厂方法模式的典型应用
public class SpringFactoryExample {
@Configuration
public static class AppConfig {
// 工厂方法创建Bean
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
// 使用FactoryBean接口
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
return factoryBean.getObject(); // 工厂方法
}
}
}
3. 日志框架中的工厂模式
public class LoggingFactoryExample {
public static void main(String[] args) {
// Log4j2的工厂方法
Logger logger = LogManager.getLogger(LoggingFactoryExample.class);
// SLF4J的工厂方法
org.slf4j.Logger slf4jLogger = org.slf4j.LoggerFactory.getLogger(LoggingFactoryExample.class);
}
}
六、工厂模式的最佳实践
1. 选择合适的工厂模式
|
场景 |
推荐模式 |
理由 |
|---|---|---|
|
产品类型固定,不会频繁扩展 |
简单工厂模式 |
实现简单 |
|
需要支持产品家族扩展 |
工厂方法模式 |
符合开闭原则 |
|
需要创建相关产品族 |
抽象工厂模式 |
保证产品兼容性 |
|
对象创建过程复杂 |
任何工厂模式 |
封装复杂创建逻辑 |
2. 使用依赖注入
// 结合Spring的依赖注入
@Service
public class OrderService {
private final PaymentFactory paymentFactory;
// 通过构造器注入工厂
public OrderService(PaymentFactory paymentFactory) {
this.paymentFactory = paymentFactory;
}
public void processOrder(Order order, String paymentType) {
Payment payment = paymentFactory.createPayment(paymentType);
payment.pay(order.getAmount());
}
}
// 配置类
@Configuration
public class FactoryConfig {
@Bean
public PaymentFactory paymentFactory() {
return new PaymentFactory();
}
}
3. 使用枚举优化工厂
public enum CarFactory {
BENZ {
@Override
public Car createCar() {
return new BenzCar();
}
},
BMW {
@Override
public Car createCar() {
return new BMWCar();
}
},
AUDI {
@Override
public Car createCar() {
return new AudiCar();
}
};
public abstract Car createCar();
// 静态工厂方法
public static Car createCar(String type) {
return valueOf(type.toUpperCase()).createCar();
}
}
// 使用示例
Car benz = CarFactory.BENZ.createCar();
Car bmw = CarFactory.createCar("bmw");
七、总结
三种工厂模式对比
|
特性 |
简单工厂模式 |
工厂方法模式 |
抽象工厂模式 |
|---|---|---|---|
|
创建对象方式 |
静态方法 |
工厂方法 |
工厂接口 |
|
扩展性 |
违反开闭原则 |
符合开闭原则 |
符合开闭原则 |
|
复杂度 |
简单 |
中等 |
复杂 |
|
适用场景 |
产品类型固定 |
产品等级结构稳定 |
产品族经常变化 |
核心价值
-
解耦:将对象创建与使用分离
-
可维护性:集中管理创建逻辑
-
可扩展性:易于添加新产品
-
可测试性:便于单元测试和Mock
工厂模式是面向对象设计中最重要的模式之一,深入理解并合理运用工厂模式,可以显著提高代码的质量和可维护性。
1498

被折叠的 条评论
为什么被折叠?



