定义
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
结构
抽象工厂与工厂方法的对比说明
1)核心对比
维度 | 工厂方法模式 | 抽象工厂模式 |
---|---|---|
产品结构 | 单一产品等级结构 | 多个产品等级结构 |
抽象产品数量 | 1个抽象产品接口/类 | 多个抽象产品接口/类 |
工厂职责 | 每个具体工厂只创建 1 种具体产品 | 每个具体工厂可创建多个相关产品(产品族) |
2)扩展机制
新增产品类型:
工厂方法:需新增具体产品类 + 对应 工厂类(符合开闭原则);
抽象工厂:需修改抽象工厂接口及所有实现类(违反开闭原则)。
新增产品族:
工厂方法:无法直接扩展产品族;
抽象工厂:只需新增具体工厂类(符合开闭原则)。
适用场景
适用于创建成套关联对象(如:跨平台 UI 组件家族)
使用示例
这里以jdbc的简化版设计为例。
定义抽象产品1
/**
* 抽象产品1:连接
*/
public interface Connection {
Statement createStatement();
void close();
}
定义抽象产品2
/**
* 抽象产品2:语句
*/
public interface Statement {
ResultSet executeQuery(String sql);
void close();
}
定义抽象产品3
/**
* 抽象产品3:结果集
*/
public interface ResultSet {
boolean next();
String getString(int column);
void close();
}
定义抽象工厂
/**
* 抽象工厂接口
* 这里看似之定义创建了一个产品,其实是创建一组关联产品,只不过是通过层级创建的
* 层级创建机制的本质
* Driver是根工厂:负责创建产品族的起点Connection
* Connection是子工厂:创建同系列的Statement
* Statement是末端工厂:创建配套的ResultSet
*
* 每个数据库驱动本质上定义了一整套不可分割的技术栈
*/
interface Driver {
Connection connect(String url);
}
以下是MySQL的实现示例
public class MySQLConnection implements Connection {
public Statement createStatement() {
return new MySQLStatement();
}
public void close() {
System.out.println("MySQL连接关闭");
}
}
public class MySQLStatement implements Statement {
public ResultSet executeQuery(String sql) {
System.out.println("执行MySQL查询: " + sql);
return new MySQLResultSet();
}
public void close() {
System.out.println("MySQL语句关闭");
}
}
public class MySQLResultSet implements ResultSet {
public boolean next() {
return false;
}
public String getString(int column) {
return "MySQL数据";
}
public void close() {
System.out.println("MySQL结果集关闭");
}
}
public class MySQLDriver implements Driver {
public Connection connect(String url) {
System.out.println("建立MySQL连接: " + url);
return new MySQLConnection();
}
}
以下是Oralce实现示例
public class OracleConnection implements Connection {
public Statement createStatement() {
return new OracleStatement();
}
public void close() {
System.out.println("Oracle连接关闭");
}
}
public class OracleStatement implements Statement {
public ResultSet executeQuery(String sql) {
System.out.println("执行Oracle查询: " + sql);
return new OracleResultSet();
}
public void close() {
System.out.println("Oracle语句关闭");
}
}
public class OracleResultSet implements ResultSet {
public boolean next() {
return false;
}
public String getString(int column) {
return "Oracle数据";
}
public void close() {
System.out.println("Oracle结果集关闭");
}
}
public class OracleDriver implements Driver {
public Connection connect(String url) {
System.out.println("建立Oracle连接: " + url);
return new OracleConnection();
}
}
测试
public class Client {
public static void main(String[] args) {
// 注册驱动
Driver mysqlDriver = new MySQLDriver();
// 使用MySQL产品族
Connection mysqlConn = mysqlDriver.connect("jdbc:mysql://localhost:3306/db");
Statement stmt = mysqlConn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users");
System.out.println(rs.getString(1));
// 关闭资源(实际应使用try-with-resources)
rs.close();
stmt.close();
mysqlConn.close();
}
}
springboot项目中关于工厂模式的一点理解
工厂模式在 Spring Boot 项目中显式使用的频率较低,主要是因为 Spring 框架的核心机制(IoC 容器和依赖注入)已经内建并自动化了工厂模式的核心理念。
1)Spring 本身就是“超级工厂”
1.1)IoC 容器作为工厂:Spring 的 ApplicationContext 本质上是一个高级工厂,负责创建、管理和装配对象(Bean)。开发者无需手动编写工厂类,Spring 已实现了工厂模式的全部流程。
1.2)依赖注入替代工厂调用:传统工厂模式需要显式调用 Factory.createXxx() 获取对象,而在 Spring 中只需通过 @Autowired 或构造函数注入,由容器自动提供实例。
2) Spring 提供了更灵活的依赖管理
2.1)接口与实现解耦:通过 @Autowired 注入接口时,Spring 会自动找到其实现类(如 MyService 接口有 ServiceImplA 和 ServiceImplB 两个实现)。
2.2)动态选择实现:结合 @Primary、@Qualifier 或配置文件(如 @Conditional),无需编写工厂代码即可动态切换实现。
3)Spring 原生支持工厂模式的变体
即使需要复杂创建逻辑,Spring 也提供了更优雅的替代方案:
3.1)@Bean 方法:在配置类中定义复杂对象的构建逻辑。
3.2)FactoryBean 接口:专为复杂对象设计(如集成第三方库)。