定义:
抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一种方式来封装一组具有共同主题的单个工厂,而无需指定它们的具体类。这种模式用于生成一系列相关或依赖对象的接口,而不指定它们具体的类。
抽象工厂模式通常涉及以下几个角色:
- 抽象工厂(Abstract Factory) :
- 定义用于创建一系列相关或相互依赖对象的接口,但不具体指定这些对象的具体类。
- 具体工厂(Concrete Factory) :
- 实现抽象工厂的接口,具体化创建相应的产品对象。
- 抽象产品(Abstract Product) :
- 为一系列具体产品定义接口。
- 具体产品(Concrete Product) :
- 抽象产品的具体实现,由具体工厂创建。
- 客户端(Client) :
- 仅使用由抽象工厂和抽象产品提供的接口来创建一系列相关或依赖的对象。
解决的问题:
- 支持产品族的创建 :
- 当需要创建一组相关或相互依赖的对象时,抽象工厂模式使你可以一次性创建所有相关对象,而不是分别创建。这确保了产品族内的对象是兼容的,并一起协同工作。
- 解耦产品的具体实现与客户代码 :
- 抽象工厂模式使客户端代码从具体产品的实现中解耦出来,客户端只依赖于产品的抽象接口。具体产品的实现是由工厂的具体子类来完成的,客户端不需要知道这些细节。
- 易于交换产品系列 :
- 由于工厂本身创建了所有的产品实例,所以更换产品族变得容易。更换不同的工厂可以生成不同的产品对象,而客户端代码几乎不需要做出改变。
- 增强一致性 :
- 当一组对象需要协同工作时,抽象工厂确保客户端始终只使用同一产品族中的对象,这有助于防止与特定产品族不兼容的对象的使用。
- 支持可扩展性和动态性 :
- 抽象工厂模式支持添加新的具体工厂和产品类,而不需要修改现有的代码。这符合开闭原则,对于扩展是开放的,对于修改是封闭的。
使用场景:
- 产品族的创建 :
- 当系统需要创建一系列相关或依赖的对象时,尤其是这些对象构成一个产品族,且需要确保客户端只使用同一个产品族中的对象。
- 系统配置与产品类型 :
- 当系统需要被配置为多种不同的环境之一时,每种环境都需要不同的对象组合。抽象工厂允许动态地更改系统的配置,以使用不同的产品组合。
- 强调一致性 :
- 当强调一系列相关的产品对象设计以保持一致性时,而不是强调单个产品对象。
- 封装多个系列 :
- 当需要封装多个系列中的产品创建逻辑,以隐藏具体实现并暴露统一的接口给客户端。
- 提供产品库的访问 :
- 当系统需要提供一个产品库,客户端不需要知道从库中获取对象的逻辑,只需通过抽象的接口访问即可。
- 运行时切换产品系列 :
- 当需要在运行时切换不同的产品系列时,抽象工厂允许不改变客户端代码的前提下实现这一点。
示例代码:
java
// 抽象产品
public interface AbstractProductA {
void useA();
}
public interface AbstractProductB {
void useB();
}
// 具体产品
public class ProductA1 implements AbstractProductA {
@Override
public void useA() {
System.out.println("Using ProductA1");
}
}
public class ProductB1 implements AbstractProductB {
@Override
public void useB() {
System.out.println("Using ProductB1");
}
}
public class ProductA2 implements AbstractProductA {
@Override
public void useA() {
System.out.println("Using ProductA2");
}
}
public class ProductB2 implements AbstractProductB {
@Override
public void useB() {
System.out.println("Using ProductB2");
}
}
// 抽象工厂
public interface AbstractFactory {
AbstractProductA createProductA();
AbstractProductB createProductB();
}
// 具体工厂
public class ConcreteFactory1 implements AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ProductB1();
}
}
public class ConcreteFactory2 implements AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ProductB2();
}
}
主要符合的设计原则:
- 开闭原则(Open-Closed Principle) :
- 抽象工厂模式很好地符合开闭原则。它允许在不修改现有代码的情况下引入新的工厂和产品族。当需要添加一个新的产品族时,只需创建新的具体工厂和一系列产品对象即可。
- 单一职责原则(Single Responsibility Principle) :
- 每个具体工厂类只负责创建特定的产品对象,遵循了单一职责原则。这样的设计使得工厂职责明确,同时简化了客户端与具体产品的交互。
- 依赖倒转原则(Dependency Inversion Principle) :
- 在抽象工厂模式中,客户代码依赖于抽象而不是具体的实现。这意味着客户代码通过抽象工厂和产品接口与具体的产品实例交互,而不需要关心这些产品的具体类。
- 接口隔离原则(Interface Segregation Principle) :
- 抽象工厂模式提供了一组接口,每个接口对应创建一种特定类型的产品。这符合接口隔离原则,因为客户端只需要关心它使用的那些接口,不必关心与之无关的接口。
抽象工厂模式通过提供一组接口来创建一系列相关或相互依赖的对象,而无需指定它们的具体类。这种模式支持高度的模块化,使得添加新产品族变得简单,同时保持客户代码与具体实现的解耦。
在JDK中的应用:
- Java数据库连接(JDBC) :
- JDBC提供了一个很好的抽象工厂模式例子。
java.sql.Connection
、java.sql.Statement
、java.sql.ResultSet
等接口的实现通常由数据库驱动提供。这里,java.sql.DriverManager
获取到Connection
对象的过程,实际上是使用了某个特定数据库驱动的工厂方法,这个过程隐藏了不同数据库驱动之间的差异。
- JDBC提供了一个很好的抽象工厂模式例子。
- Java XML API :
- 在处理XML时,Java的
javax.xml.parsers.DocumentBuilderFactory
和javax.xml.transform.TransformerFactory
等类为不同的XML解析器和转换器实现提供了工厂接口。这些工厂类根据环境配置或系统属性返回特定实现的实例。
- 在处理XML时,Java的
- Java加密技术(JCE) :
- Java加密扩展(JCE)框架使用工厂方法提供了加密算法的实现。例如,
javax.crypto.KeyGenerator
和javax.crypto.Cipher
类根据指定的算法名称返回特定算法的实现。
- Java加密扩展(JCE)框架使用工厂方法提供了加密算法的实现。例如,
在Spring中的应用:
- BeanFactory 和 ApplicationContext :
- 在Spring中,
BeanFactory
提供了一个高级的配置机制,用于管理任何类型的对象。ApplicationContext
是BeanFactory
的子接口,它添加了更多的企业特定的功能。这些都可以看作是抽象工厂,提供了创建和管理bean的机制。
- 在Spring中,
- FactoryBean :
- Spring中的
FactoryBean
是一个接口,用户可以通过实现这个接口来创建复杂的bean。这个接口充当了抽象工厂,而实现了FactoryBean
的类则相当于具体工厂,负责创建特定类型的对象。
- Spring中的
- 多个数据源的配置 :
- 当应用程序需要连接到多个数据库时,Spring允许配置多个数据源。每个数据源的配置可以视为一个具体工厂,创建特定于数据库类型的连接。
- Spring中的模板类 :
- 例如
JdbcTemplate
,JmsTemplate
,RestTemplate
等,这些模板类提供了与不同类型的技术进行交互的高层封装。它们背后的实现(如数据库访问技术、消息服务、REST客户端等)可以看作是通过不同的工厂创建的。
- 例如