抽象工厂模式 (Abstract Factory Pattern)
提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
模式定义
抽象工厂模式是一种创建型设计模式,它能创建一系列相关的对象而无需指定其具体类。抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
适用场景
- 系统要独立于其产品的创建、组合和表示时
- 系统要由多个产品系列中的一个来配置时
- 需要强调一系列相关的产品对象的设计以便进行联合使用时
- 提供一个产品类库,而只想显示它们的接口而不是实现时
结构图
graph TD
A[AbstractFactory] --> B{createProductA}
A --> C{createProductB}
D[ConcreteFactory1] --> E{createProductA1}
D --> F{createProductB1}
G[ConcreteFactory2] --> H{createProductA2}
G --> I{createProductB2}
J[Client] --> A
实现示例
Java 实现
// 抽象产品A
public interface ProductA {
void useA();
}
// 抽象产品B
public interface ProductB {
void useB();
}
// 具体产品A1
public class ProductA1 implements ProductA {
@Override
public void useA() {
System.out.println("使用产品A1");
}
}
// 具体产品A2
public class ProductA2 implements ProductA {
@Override
public void useA() {
System.out.println("使用产品A2");
}
}
// 具体产品B1
public class ProductB1 implements ProductB {
@Override
public void useB() {
System.out.println("使用产品B1");
}
}
// 具体产品B2
public class ProductB2 implements ProductB {
@Override
public void useB() {
System.out.println("使用产品B2");
}
}
// 抽象工厂
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂1
public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ProductA1();
}
@Override
public ProductB createProductB() {
return new ProductB1();
}
}
// 具体工厂2
public class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ProductA2();
}
@Override
public ProductB createProductB() {
return new ProductB2();
}
}
经典案例
1. Java SE中的抽象工厂模式
Java标准库中的许多地方都使用了抽象工厂模式,例如JDBC API:
// DriverManager是抽象工厂的客户端
public class JdbcExample {
public static void main(String[] args) {
try {
// 通过抽象工厂创建具体的数据库连接
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/test", "user", "password");
// 创建Statement对象
Statement stmt = conn.createStatement();
// 执行查询
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
// 处理结果
while (rs.next()) {
System.out.println(rs.getString("name"));
}
// 关闭资源
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// DriverManager内部使用了抽象工厂模式
// 不同的数据库厂商提供具体的工厂实现
// 例如MySQL的com.mysql.cj.jdbc.Driver
// 例如PostgreSQL的org.postgresql.Driver
2. Spring框架中的抽象工厂应用
Spring框架中也大量使用了抽象工厂模式的思想:
// Spring中的BeanFactory就是抽象工厂模式的体现
public interface BeanFactory {
Object getBean(String name) throws BeansException;
T getBean(String name, Class requiredType) throws BeansException;
T getBean(Class requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
// ... 其他方法
}
// 不同的工厂实现
// DefaultListableBeanFactory
// XmlBeanFactory
// AnnotationConfigApplicationContext
// 等等都是具体的工厂实现
// 使用示例
@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
// 返回具体的数据源实现
return new HikariDataSource();
}
@Bean
public JdbcTemplate jdbcTemplate() {
// 使用工厂方法创建JdbcTemplate
return new JdbcTemplate(dataSource());
}
}
3. 跨平台UI工具包
跨平台UI工具包是抽象工厂模式的经典应用场景:
// 抽象产品接口
public interface Button {
void render();
void onClick();
}
public interface Checkbox {
void render();
void toggle();
}
// Windows具体产品
public class WindowsButton implements Button {
public void render() {
System.out.println("渲染Windows风格按钮");
}
public void onClick() {
System.out.println("Windows按钮被点击");
}
}
public class WindowsCheckbox implements Checkbox {
public void render() {
System.out.println("渲染Windows风格复选框");
}
public void toggle() {
System.out.println("Windows复选框状态切换");
}
}
// Mac具体产品
public class MacButton implements Button {
public void render() {
System.out.println("渲染Mac风格按钮");
}
public void onClick() {
System.out.println("Mac按钮被点击");
}
}
public class MacCheckbox implements Checkbox {
public void render() {
System.out.println("渲染Mac风格复选框");
}
public void toggle() {
System.out.println("Mac复选框状态切换");
}
}
// 抽象工厂
public interface UIFactory {
Button createButton();
Checkbox createCheckbox();
}
// Windows工厂
public class WindowsFactory implements UIFactory {
public Button createButton() {
return new WindowsButton();
}
public Checkbox createCheckbox() {
return new WindowsCheckbox();
}
}
// Mac工厂
public class MacFactory implements UIFactory {
public Button createButton() {
return new MacButton();
}
public Checkbox createCheckbox() {
return new MacCheckbox();
}
}
// 应用程序类
public class Application {
private Button button;
private Checkbox checkbox;
public Application(UIFactory factory) {
button = factory.createButton();
checkbox = factory.createCheckbox();
}
public void paint() {
button.render();
checkbox.render();
}
public void clickButton() {
button.onClick();
}
public void toggleCheckbox() {
checkbox.toggle();
}
}
// 客户端代码
public class ApplicationRunner {
public static void main(String[] args) {
UIFactory factory;
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) {
factory = new WindowsFactory();
} else if (osName.contains("mac")) {
factory = new MacFactory();
} else {
// 默认工厂
factory = new WindowsFactory();
}
Application app = new Application(factory);
app.paint();
app.clickButton();
app.toggleCheckbox();
}
}
优缺点
优点
- 确保客户端始终只使用同一个产品族中的对象
- 易于交换产品系列,只需更换具体工厂即可
- 有利于产品的一致性,保证产品间的约束关系
缺点
- 难以支持新种类的产品,扩展新产品需要修改抽象工厂接口
- 增加了系统的抽象性和复杂度