抽象工厂(Abstract Factory)模式可以让客户端使用一组相关或独立的工厂来创建对象,而不需要直接指定类。它将一组相关的产品组合在一起,为一些功能相似的产品提供一个抽象的接口。
什么是抽象工厂模式
抽象工厂模式是一种创建型设计模式,它将一组相关的产品组合在一起,为一些功能相似的产品提供一个抽象的接口,它的核心是抽象工厂接口和具体工厂实现。抽象工厂接口定义了产品族的创建方法,具体工厂实现则负责创建具体的产品。
抽象工厂模式中,通常有四种参与者:抽象工厂、具体工厂、抽象产品、具体产品。其中,抽象产品和具体产品都是工厂创建的对象,而抽象工厂和具体工厂则是创建工厂对象的工厂。
抽象工厂模式的应用场景
抽象工厂模式通常适用于以下场景:
-
需要创建一组相互依赖或关联的对象。例如,创建一个图形界面的工厂,需要创建一组按钮、文本框、下拉菜单等相互依赖的控件。
-
系统中有多个产品族,且客户端只使用其中的某一族。因为抽象工厂可以提供多个产品族,所以如果系统需要支持多个产品族,同时客户端只需要使用其中的某一个族,那么就可以使用抽象工厂模式。例如,在游戏中需要创建两个不同类型的兵种,同时客户端只需要使用其中的一个兵种。
-
需要强制约束产品的使用方式,以保证产品使用的正确性和一致性。抽象工厂模式可以约束产品的使用方式,使得客户端只能通过工厂对象来获取产品,而不能直接创建产品,从而保证了产品使用的正确性和一致性。
抽象工厂模式的代码示例
该示例中定义了两个产品族:Fruit(水果)和Drink(饮料)。 Fruit 由苹果和香蕉两个实现类构成, Drink 由可乐和橙汁两个实现类构成。两个产品族是互不相关的。
//抽象产品:水果
interface Fruit {
void show();
}
//具体产品:苹果
class Apple implements Fruit {
@Override
public void show() {
System.out.println("苹果");
}
}
//具体产品:香蕉
class Banana implements Fruit {
@Override
public void show() {
System.out.println("香蕉");
}
}
//抽象产品:饮料
interface Drink {
void show();
}
//具体产品:可乐
class Cola implements Drink {
@Override
public void show() {
System.out.println("可乐");
}
}
//具体产品:橙汁
class OrangeJuice implements Drink {
@Override
public void show() {
System.out.println("橙汁");
}
}
抽象工厂接口定义了 Fruit 和 Drink 两个产品族的创建方法,具体工厂实现则负责创建具体的产品。
//抽象工厂:提供创建水果和饮料的方法
interface Factory {
Fruit createFruit();
Drink createDrink();
}
//具体工厂:提供创建苹果和可乐的方法
class AppleColaFactory implements Factory {
@Override
public Fruit createFruit() {
return new Apple();
}
@Override
public Drink createDrink() {
return new Cola();
}
}
//具体工厂:提供创建香蕉和橙汁的方法
class BananaOrangeJuiceFactory implements Factory {
@Override
public Fruit createFruit() {
return new Banana();
}
@Override
public Drink createDrink() {
return new OrangeJuice();
}
}
客户端代码通过工厂获取产品。
//客户端测试
public class AbstractFactoryExample {
public static void main(String[] args) {
Factory factory1 = new AppleColaFactory(); // 创建苹果可乐工厂
Fruit apple = factory1.createFruit(); // 获取苹果对象
Drink cola = factory1.createDrink(); // 获取可乐对象
apple.show(); // 输出苹果
cola.show(); // 输出可乐
Factory factory2 = new BananaOrangeJuiceFactory(); // 创建香蕉橙汁工厂
Fruit banana = factory2.createFruit(); // 获取香蕉对象
Drink orangeJuice = factory2.createDrink(); // 获取橙汁对象
banana.show(); // 输出香蕉
orangeJuice.show(); // 输出橙汁
}
}
输出:
苹果
可乐
香蕉
橙汁
抽象工厂模式的实际应用
以下是几个在实际开发中常用的框架或库,它们都用到了抽象工厂模式:
-
JDBC:Java 数据库连接技术,使用了抽象工厂模式来提供一个标准的接口,可以通过不同的工厂实现类来获取适用于不同数据库类型的 Connection、Statement、ResultSet 等对象,从而实现多数据库操作的无差别性。
-
Hibernate:Java 的 ORM 框架,也使用了抽象工厂模式,通过抽象工厂模式来对底层的 JDBC 进行封装,为应用程序提供一个工厂接口,通过这个接口可以得到不同数据库的 Session 实例、Transaction 实例等对象。
-
Swing:Java 的 GUI 组件库,使用了抽象工厂模式来提供一组用于创建 GUI 组件的抽象工厂接口,通过这些接口可以提供不同风格的窗口、按钮、文本框等组件,从而实现在不同操作系统下的统一的 GUI 设计。
-
JDBC Template:Spring 框架中用于简化 JDBC 操作的模板类,使用了抽象工厂模式,为不同类型和不同厂商的数据库提供统一的操作接口。
-
RestTemplate:Spring 框架中用于在 Web 应用程序中进行 RESTful 服务的客户端工具,也使用了抽象工厂模式,提供了一个抽象工厂接口,专门用于创建请求和处理响应。具体实现类可以使用不同的 HTTP 库,如 apache HttpClient、okHttp 等。
总结
通过抽象工厂模式,我们可以将多个相关联但是具有不同特征的对象组合到一起,并提供一个抽象的接口,使得用户可以使用这些对象无需知道其具体实现。这就是抽象工厂模式的优势。它的缺陷在于:如果我们需要在产品家族中增加一个新的产品,那么每一个工厂类都需要添加一个从抽象工厂继承来的方法来创建该新产品,不仅拓展麻烦,也会导致一定的修改工作量。
关注微信公众号:“小虎哥的技术博客”。我们会定期发布关于Java技术的详尽文章,让您能够深入了解该领域的各种技巧和方法,让我们一起成为更优秀的程序员👩💻👨💻!