写在前面
Hello,我是易元,本文主要详细介绍工厂模式的分类、定义及其在实际场景中的使用,若内容有误,请大家留言指正!!
前言
工厂模式(Factory Pattern)是一种创建型设计模式,提供了一种创建对象的方式,而无需指定具体的类。
工厂模式的核心思想是将对象的创建过程进行封装,使得客户端代码与具体类的实现解耦。
创建型设计模式共有五种:
工厂方法模式、抽象工厂模式、建造者模式、原型模式、单例模式。
分类
工厂模式主要分为三种:
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Method)
- 抽象工厂模式(Abstract Factory)
简单工厂模式
定义
简单工厂模式通过一个工厂类来创建不同类型的对象,客户端只需要传递参数即可获取所需对象。
工厂方法模式中定义了一个抽象工厂类,并且定义了创建产品对象的公共接口,返回抽象产品对象,抽象工厂子类实现了抽象接口,返回具体产品对象。
使用场景
- 对象的创建逻辑简单。
- 客户端不需要关心对象的创建细节。
简单示例
产品接口
public interface Product {
void use();
}
具体产品
public class ProductA implements Product {
@Override
public void use() {
System.out.println("使用产品 A");
}
}
public class ProductB implements Product {
@Override
public void use() {
System.out.println("使用产品 B");
}
}
简单工厂类
public class SimpleFactory {
public static Product createProduct(String type) {
if ("A".equals(type)) {
return new ProductA();
} else if ("B".equals(type)) {
return new ProductB();
}
throw new IllegalArgumentException("未知产品类型!");
}
}
客户端代码
public class Client {
public static void main(String[] args) {
Product productA = SimpleFactory.createProduct("A");
productA.use(); // 输出: 使用产品 A
Product productB = SimpleFactory.createProduct("B");
productB.use(); // 输出: 使用产品 B
}
}
工厂方法模式
定义
工厂方法模式定义了一个创建对象的接口,但由子类决定实例化具体的类,将对象的创建延迟到子类。
将对象的创建延迟到子类解释:工厂方法模式中定义了一个抽象工厂类,并且定义了创建产品对象的公共接口,返回抽象产品对象,抽象工厂子类实现了抽象接口,返回具体产品对象。
使用场景
- 对象的创建逻辑复杂,需要根据不同条件创建不同对象。
- 需要扩展时,可以通过新增子类来实现。
简单示例
产品接口
public interface Product {
void use();
}
具体产品
public class ProductA implements Product {
@Override
public void use() {
System.out.println("使用产品 A");
}
}
public class ProductB implements Product {
@Override
public void use() {
System.out.println("使用产品 B");
}
}
工厂接口
public interface Factory {
Product createProduct();
}
具体工厂
public class FactoryA implements Factory {
@Override
public Product createProduct() {
return new ProductA();
}
}
public class FactoryB implements Factory {
@Override
public Product createProduct() {
return new ProductB();
}
}
客户端代码
public class Client {
public static void main(String[] args) {
Factory factoryA = new FactoryA();
// 由子类创建产品对象
Product productA = factoryA.createProduct();
productA.use(); // 输出: 使用产品 A
Factory factoryB = new FactoryB();
Product productB = factoryB.createProduct();
productB.use(); // 输出: 使用产品 B
}
}
实际使用案例
在 Spring Framework 中的使用
工厂接口BeanFactory
Spring中最基础的工厂接口,定义了获取Bean的方法。
public interface BeanFactory {
Object getBean(String name) throws BeansException; // 通过名称获取 Bean
<T> T getBean(String name, Class<T> requiredType) throws BeansException; // 通过名称和类型获取 Bean
<T> T getBean(Class<T> requiredType) throws BeansException; // 通过类型获取 Bean
boolean containsBean(String name); // 检查是否包含指定名称的 Bean
}
具体工厂实现 ClassPathXmlApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyBean myBean = context.getBean(MyBean.class);
产品接口可以理解为Spring管理的Bean的通用接口(自定义创建的接口类),而具体产品则是这些Bean的具体实现(自定义创建的实现类)。
ClassPathXmlApplicationContext为ApplicationContext的实现类ApplicationContext是BeanFactory的子接口,对BeanFactory进行了扩展,例如:国际化、事件发布等public interface ApplicationContext extends Bean>Factory { String getApplicationName(); // 获取应用名称 String getDisplayName(); // 获取显示名称 long getStartupDate(); // 获取启动时间 void publishEvent(ApplicationEvent event); >// 发布事件 }
抽象工厂模式
定义
抽象工厂模式提供了一个创建一系列相关或相互依赖对象的接口,无需指定它们的具体类。
使用场景
- 需要创建一组相关或依赖的对象
- 系统中有多个产品族,且客户端只使用其中某一族产品。
简单示例
产品接口
public interface Product {
void use();
}
具体产品
public class ProductA1 implements Product {
@Override
public void use() {
System.out.println("使用产品 A1");
}
}
public class ProductA2 implements Product {
@Override
public void use() {
System.out.println("使用产品 A2");
}
}
public class ProductB1 implements Product {
@Override
public void use() {
System.out.println("使用产品 B1");
}
}
public class ProductB2 implements Product {
@Override
public void use() {
System.out.println("使用产品 B2");
}
}
抽象工厂接口
public interface AbstractFactory {
Product createProduct1();
Product createProduct2();
}
具体工厂
// A 类型产品
public class FactoryA implements AbstractFactory {
@Override
public Product createProduct1() {
return new ProductA1();
}
@Override
public Product createProduct2() {
return new ProductA2();
}
}
// B 类型产品
public class FactoryB implements AbstractFactory {
@Override
public Product createProduct1() {
return new ProductB1();
}
@Override
public Product createProduct2() {
return new ProductB2();
}
}
客户端代码
public class Client {
public static void main(String[] args) {
AbstractFactory factoryA = new FactoryA();
Product productA1 = factoryA.createProduct1();
Product productA2 = factoryA.createProduct2();
productA1.use(); // 输出: 使用产品 A1
productA2.use(); // 输出: 使用产品 A2
AbstractFactory factoryB = new FactoryB();
Product productB1 = factoryB.createProduct1();
Product productB2 = factoryB.createProduct2();
productB1.use(); // 输出: 使用产品 B1
productB2.use(); // 输出: 使用产品 B2
}
}
实际使用案例
在 MyBatis 中的使用
抽象工厂SqlSessionFactory
SqlSessionFactory 是 MyBatis 的核心接口,定义了创建 SqlSession 的方法.
public interface SqlSessionFactory {
SqlSession openSession(); // 创建 SqlSession
SqlSession openSession(boolean autoCommit); // 创建 SqlSession,指定是否自动提交
SqlSession openSession(Connection connection); // 创建 SqlSession,使用指定的数据库连接
Configuration getConfiguration(); // 获取配置信息
}
具体工厂DefaultSqlSessionFactory
DefaultSqlSessionFactory 是 SqlSessionFactory 的具体实现类,负责创建 SqlSession 对象。
public class DefaultSqlSessionFactory implements SqlSessionFactory {
private final Configuration configuration;
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
@Override
public SqlSession openSession(boolean autoCommit) {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
}
@Override
public SqlSession openSession(Connection connection) {
return openSessionFromConnection(configuration.getDefaultExecutorType(), connection);
}
@Override
public Configuration getConfiguration() {
return configuration;
}
// 创建 SqlSession 的具体逻辑
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
}
// 创建 SqlSession 的具体逻辑
private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
}
}
抽象产品SqlSession
SqlSession 是 MyBatis 的核心接口,定义了执行 SQL 命令、获取映射器等。
public interface SqlSession extends Closeable {
<T> T selectOne(String statement); // 查询单条记录
<T> T selectOne(String statement, Object parameter); // 查询单条记录,带参数
<E> List<E> selectList(String statement); // 查询多条记录
<E> List<E> selectList(String statement, Object parameter); // 查询多条记录,带参数
int insert(String statement); // 插入记录
int insert(String statement, Object parameter); // 插入记录,带参数
int update(String statement); // 更新记录
int update(String statement, Object parameter); // 更新记录,带参数
int delete(String statement); // 删除记录
int delete(String statement, Object parameter); // 删除记录,带参数
void commit(); // 提交事务
void rollback(); // 回滚事务
<T> T getMapper(Class<T> type); // 获取映射器
Connection getConnection(); // 获取数据库连接
}
具体产品DefaultSqlSession
DefaultSqlSession 是 SqlSession 的具体实现类,负责执行 SQL 命令、管理事务等。
public class DefaultSqlSession implements SqlSession {
private final Configuration configuration;
private final Executor executor;
private final boolean autoCommit;
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
this.configuration = configuration;
this.executor = executor;
this.autoCommit = autoCommit;
}
@Override
public <T> T selectOne(String statement) {
return selectOne(statement, null);
}
@Override
public <T> T selectOne(String statement, Object parameter) {
List<T> list = selectList(statement, parameter);
if (list.size() == 1) {
return list.get(0);
} else if (list.size() > 1) {
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
@Override
public <E> List<E> selectList(String statement) {
return selectList(statement, null);
}
@Override
public <E> List<E> selectList(String statement, Object parameter) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.query(ms, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
...
}
长话短说
- 简单工厂模式:一个工厂类负责创建所有产品。
- 工厂方法模式:每个产品对应一个工厂类。
- 抽象工厂模式:每个工厂类负责创建一组相关产品。
何时可以使用?
对象的创建逻辑复杂
- 若对象的创建过程涉及到复杂的初始化逻辑(如 配置加载,依赖注入等等),可以使用工厂模式将创建的逻辑封装起来以便后期维护。
需要支持多种实现
- 若系统需要支持多种实现(如多种支付方式、多数据库类型等),可以使用工厂模式动态的创建对象。
需要解耦客户端与具体实现
- 若客户端代码需要与具体实现进行解耦,可以使用工厂模式隐藏具体实现细节。
需要集中管理对象的创建
- 若对象的创建逻辑分散在多个地方,可以使用工厂模式将创建的逻辑集中管理。
需要动态扩展
- 若在开发中预见可能存在新的产品类型,可以预先使用工厂模式以便当新的产品出现时动态的扩展。
如何使用?四步走!
定义产品接口
- 定义产品的通用接口或抽象类。
实现具体产品
- 实现产品接口,定义具体产品的行为。
定义工厂接口
- 定义工厂接口,在其中声明产品的创建方法。
实现具体工厂
- 实现工厂接口,创建具体产品。