设计模式之抽象工厂模式
目录
- 定义
- 结构
- 抽象工厂与工厂方法的对比说明
- 适用场景
- 使用示例
- springboot项目中关于工厂模式的一点理解
定义
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
结构
抽象工厂与工厂方法的对比说明
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 接口:专为复杂对象设计(如集成第三方库)。