# 抽象工厂模式
# 概念
抽象工厂模式( Abstract Factory Pattern )是一种创建型设计模式,它围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂。
抽象工厂模式提供了一种方式,可以创建一系列相关或相互依赖的对象,而无需指定它们具体的类。抽象工厂模式强调的是一个工厂类可以创建一组相关的产品对象,这些对象通常属于一个产品族。
# 作用
解耦客户端与具体产品:客户端代码只需要依赖抽象工厂和抽象产品,无需关心具体产品的创建和实现细节。
易于扩展产品族:如果需要支持新的产品族(如 Linux 风格的 UI 组件),只需添加一个新的具体工厂和具体产品,无需修改现有代码。
保证产品的一致性:通过工厂创建的一组产品是相互兼容的,属于同一个产品族。
# 场景
跨平台兼容:适配多平台(如 Windows/Mac ),提供风格一致的 UI 组件或服务。
产品族扩展:新增产品族(如 Linux UI )无需改代码,符合开闭原则。
强制产品兼容:确保对象配套使用(如统一游戏皮肤/硬件驱动)。
动态切换配置:运行时切换整组对象(如主题/支付网关)。
框架可插拔设计:框架支持第三方扩展(如 Spring 工厂/日志适配器)。
# 举例
假设我们正在开发一个跨平台的应用程序,需要为不同的操作系统(如 Windows 和 Mac )提供不同的UI组件。我们可以使用抽象工厂模式来创建这些UI组件。
抽象产品( Abstract Product ):
package net.feixiang.creational.abstractFactory;
/**
* 按钮接口
*/
public interface Button {
/**
* 渲染按钮
*/
void render();
}
package net.feixiang.creational.abstractFactory;
/**
* 文本框接口
*/
public interface TextBox {
/**
* 渲染文本框
*/
void render();
}
抽象工厂( Abstract Factory ):
package net.feixiang.creational.abstractFactory;
/**
* 定义创建不同类型 GUI 组件的方法。具体的工厂类将实现这个接口来创建特定的组件。
*/
public interface GUIFactory {
/**
* 创建按钮
*
* @return 按钮
*/
Button createButton();
/**
* 创建文本框
*
* @return 文本框
*/
TextBox createTextBox();
}
具体产品( Concrete Product ):
package net.feixiang.creational.abstractFactory;
/**
* Windows 风格的按钮实现
*/
public class WindowsButton implements Button {
@Override
public void render() {
System.out.println("渲染 Windows 风格的按钮");
}
}
package net.feixiang.creational.abstractFactory;
/**
* Windows 风格的文本框实现
*/
public class WindowsTextBox implements TextBox {
@Override
public void render() {
System.out.println("渲染 Windows 风格的文本框");
}
}
package net.feixiang.creational.abstractFactory;
/**
* Mac 风格的按钮实现
*/
public class MacButton implements Button {
@Override
public void render() {
System.out.println("渲染 Mac 风格的按钮");
}
}
package net.feixiang.creational.abstractFactory;
/**
* Mac 风格的文本框实现
*/
public class MacTextBox implements TextBox {
@Override
public void render() {
System.out.println("渲染 Mac 风格的文本框");
}
}
具体工厂( Concrete Factory ):
package net.feixiang.creational.abstractFactory;
/**
* Windows 风格的 GUI 工厂实现
*/
public class WindowsFactory implements GUIFactory {
@Override
public Button createButton() {
System.out.println("创建 Windows 风格的按钮");
return new WindowsButton();
}
@Override
public TextBox createTextBox() {
System.out.println("创建 Windows 风格的文本框");
return new WindowsTextBox();
}
}
package net.feixiang.creational.abstractFactory;
/**
* Mac 风格的 GUI 工厂实现
*/
public class MacFactory implements GUIFactory {
@Override
public Button createButton() {
System.out.println("创建 Mac 风格的按钮");
return new MacButton();
}
@Override
public TextBox createTextBox() {
System.out.println("创建 Mac 风格的文本框");
return new MacTextBox();
}
}
运行示例:
package net.feixiang.creational.abstractFactory;
/**
* 抽象工厂模式示例
*/
public class AbstractFactoryDemo {
private final GUIFactory factory;
public AbstractFactoryDemo(GUIFactory factory) {
this.factory = factory;
}
/**
* 创建用户界面
* 根据不同的操作系统,创建不同风格的按钮和文本框
*/
public void createUI() {
Button button = factory.createButton();
TextBox textBox = factory.createTextBox();
button.render();
textBox.render();
}
public static void main(String[] args) {
// 输出当前操作系统
System.out.println("当前操作系统: " + System.getProperty("os.name"));
// 根据操作系统选择工厂
GUIFactory factory;
if (System.getProperty("os.name").contains("Windows")) {
factory = new WindowsFactory();
} else {
factory = new MacFactory();
}
// 如果有其它系统,直接在这里新增实现类,不需要修改GUIFactory和createUI()
// 例如:factory = new LinuxFactory();
// 创建应用程序实例
AbstractFactoryDemo app = new AbstractFactoryDemo(factory);
app.createUI();
}
}
控制台输出:
当前操作系统: Windows 11
创建 Windows 风格的按钮
创建 Windows 风格的文本框
渲染 Windows 风格的按钮
渲染 Windows 风格的文本框
# 反例
假设我们直接在客户端代码中创建 UI 组件,而不使用抽象工厂模式:
package net.feixiang.creational.abstractFactory.contrary;
import net.feixiang.creational.abstractFactory.*;
/**
* 非抽象工厂模式示例
* 这种方式不符合抽象工厂模式的设计原则,因为每次添加新的操作系统都需要
* 修改 createUI() 方法,这会导致代码的可维护性和可扩展性变差。
*/
public class NonAbstractFactoryDemo {
public void createUI() {
Button button;
TextBox textBox;
if (System.getProperty("os.name").contains("Windows")) {
button = new WindowsButton();
textBox = new WindowsTextBox();
} else {
button = new MacButton();
textBox = new MacTextBox();
}
// 如果有其它系统,这些需要新增 if else 代码,即需要更改 createUI() 方法
button.render();
textBox.render();
}
public static void main(String[] args) {
// 输出当前操作系统
System.out.println("当前操作系统: " + System.getProperty("os.name"));
NonAbstractFactoryDemo app = new NonAbstractFactoryDemo();
app.createUI();
}
}
控制台输出:
当前操作系统: Windows 11
渲染 Windows 风格的按钮
渲染 Windows 风格的文本框
# 解析
代码耦合度高
客户端代码直接依赖于具体产品类(如 WindowsButton、MacButton 等),如果需要添加新的产品族(如 Linux 风格的 UI 组件),必须修改客户端代码,违反了开闭原则。
难以维护和扩展
每次添加新的产品族时,都需要在多个地方修改代码,容易引入错误。
无法保证产品的一致性
如果客户端代码在不同地方创建了不一致的产品组合,可能会导致系统行为异常。
通过使用抽象工厂模式,可以有效解决这些问题,提高代码的可维护性和扩展性。
总结
抽象工厂模式作用是解耦客户端与具体产品,让客户端只依赖抽象;易于扩展产品族,新增产品族无需改现有代码;保证产品一致性,创建的产品相互兼容。
实现时先定义抽象工厂接口,声明创建相关产品的方法;再实现具体工厂类,针对不同产品族创建对应实例;定义抽象产品接口,声明通用行为;实现具体产品类;客户端通过抽象工厂动态选择具体工厂来创建一组相关产品。

微信公众号

QQ交流群
如若发现错误,诚心感谢反馈。
愿你倾心相念,愿你学有所成。
愿你朝华相顾,愿你前程似锦。