抽象工厂模式
大约 7 分钟
抽象工厂模式
什么是抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂模式是工厂方法模式的升级版,它关注的是产品族的创建。
抽象工厂模式的核心思想是:
- 提供一个创建一系列相关或相互依赖对象的接口
- 无需指定它们具体的类
- 强调产品族的概念,即一系列相关的产品对象
为什么需要抽象工厂模式
在实际开发中,我们经常需要创建一组相关或相互依赖的对象。如果使用工厂方法模式,我们需要为每个产品都创建一个工厂,这样会导致类的数量急剧增加。抽象工厂模式通过将相关的产品组织在一起,提供一个统一的接口来创建整个产品族,从而解决了这个问题。
抽象工厂模式的结构
抽象工厂模式包含以下几个角色:
- 抽象产品(AbstractProduct):为一类产品声明接口
- 具体产品(ConcreteProduct):实现抽象产品接口的具体产品类
- 抽象工厂(AbstractFactory):声明创建抽象产品对象的接口
- 具体工厂(ConcreteFactory):实现抽象工厂接口,创建具体产品对象
抽象工厂模式的实现
基本实现
// 抽象产品A
interface AbstractProductA {
void useA();
}
// 抽象产品B
interface AbstractProductB {
void useB();
}
// 具体产品A1
class ConcreteProductA1 implements AbstractProductA {
@Override
public void useA() {
System.out.println("使用产品A1");
}
}
// 具体产品A2
class ConcreteProductA2 implements AbstractProductA {
@Override
public void useA() {
System.out.println("使用产品A2");
}
}
// 具体产品B1
class ConcreteProductB1 implements AbstractProductB {
@Override
public void useB() {
System.out.println("使用产品B1");
}
}
// 具体产品B2
class ConcreteProductB2 implements AbstractProductB {
@Override
public void useB() {
System.out.println("使用产品B2");
}
}
// 抽象工厂
interface AbstractFactory {
AbstractProductA createProductA();
AbstractProductB createProductB();
}
// 具体工厂1
class ConcreteFactory1 implements AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB1();
}
}
// 具体工厂2
class ConcreteFactory2 implements AbstractFactory {
@Override
public AbstractProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public AbstractProductB createProductB() {
return new ConcreteProductB2();
}
}
实际应用示例
// 用户界面组件接口
interface Button {
void render();
}
interface Checkbox {
void render();
}
// Windows风格按钮
class WindowsButton implements Button {
@Override
public void render() {
System.out.println("渲染Windows风格按钮");
}
}
// Mac风格按钮
class MacButton implements Button {
@Override
public void render() {
System.out.println("渲染Mac风格按钮");
}
}
// Windows风格复选框
class WindowsCheckbox implements Checkbox {
@Override
public void render() {
System.out.println("渲染Windows风格复选框");
}
}
// Mac风格复选框
class MacCheckbox implements Checkbox {
@Override
public void render() {
System.out.println("渲染Mac风格复选框");
}
}
// 抽象UI工厂
interface UIFactory {
Button createButton();
Checkbox createCheckbox();
}
// Windows UI工厂
class WindowsFactory implements UIFactory {
@Override
public Button createButton() {
return new WindowsButton();
}
@Override
public Checkbox createCheckbox() {
return new WindowsCheckbox();
}
}
// Mac UI工厂
class MacFactory implements UIFactory {
@Override
public Button createButton() {
return new MacButton();
}
@Override
public Checkbox createCheckbox() {
return new MacCheckbox();
}
}
// 应用程序类
class Application {
private Button button;
private Checkbox checkbox;
public Application(UIFactory factory) {
button = factory.createButton();
checkbox = factory.createCheckbox();
}
public void render() {
button.render();
checkbox.render();
}
}
// 使用示例
public class AbstractFactoryDemo {
public static void main(String[] args) {
// 创建Windows风格的UI
UIFactory windowsFactory = new WindowsFactory();
Application windowsApp = new Application(windowsFactory);
System.out.println("Windows风格UI:");
windowsApp.render();
System.out.println();
// 创建Mac风格的UI
UIFactory macFactory = new MacFactory();
Application macApp = new Application(macFactory);
System.out.println("Mac风格UI:");
macApp.render();
}
}
抽象工厂模式的应用场景
- 跨平台UI框架:为不同操作系统提供一致的UI组件
- 游戏开发:为不同种族或阵营创建一系列相关的游戏对象
- 数据库访问层:为不同数据库提供一致的访问接口
- 主题切换:为应用程序提供不同的视觉主题
- 产品族创建:需要创建一组相关的产品对象
抽象工厂模式的优缺点
优点
- 产品族一致性:确保创建的产品族中的对象是相互兼容的
- 符合开闭原则:新增产品族时,只需新增具体工厂类,无需修改原有代码
- 符合单一职责原则:每个工厂类只负责创建对应的产品族
- 良好的封装性:客户端不需要知道所创建具体产品的类名,只需知道对应的工厂即可
缺点
- 难以扩展产品等级结构:新增产品等级结构时,需要修改抽象工厂接口及其所有实现类
- 类数量增加:每增加一个产品族,就需要增加一组具体产品类和一个具体工厂类
- 增加了系统的抽象性和复杂度:需要引入多个抽象层,增加了系统的抽象性和理解难度
抽象工厂模式与其他创建型模式的比较
与工厂方法模式的区别
- 工厂方法模式:针对单一产品等级结构,一个工厂创建一个产品
- 抽象工厂模式:针对多个产品等级结构,一个工厂创建一系列相关的产品
与建造者模式的区别
- 抽象工厂模式:强调产品族的创建,关注的是创建对象的过程
- 建造者模式:强调复杂对象的构建过程,关注的是对象的表示
抽象工厂模式的变体
1. 配置文件驱动的抽象工厂
// 通过配置文件确定具体工厂
class FactoryProducer {
public static AbstractFactory getFactory(String factoryType) {
if ("Windows".equalsIgnoreCase(factoryType)) {
return new WindowsFactory();
} else if ("Mac".equalsIgnoreCase(factoryType)) {
return new MacFactory();
}
return null;
}
}
// 使用配置文件
public class ConfigurableDemo {
public static void main(String[] args) {
// 从配置文件读取工厂类型
String factoryType = "Windows"; // 实际中从配置文件读取
AbstractFactory factory = FactoryProducer.getFactory(factoryType);
if (factory != null) {
Button button = factory.createButton();
Checkbox checkbox = factory.createCheckbox();
button.render();
checkbox.render();
}
}
}
2. 单例抽象工厂
// 单例抽象工厂实现
class SingletonFactoryProducer {
private static final Map<String, AbstractFactory> factoryMap = new HashMap<>();
static {
factoryMap.put("Windows", new WindowsFactory());
factoryMap.put("Mac", new MacFactory());
}
public static AbstractFactory getFactory(String factoryType) {
return factoryMap.get(factoryType);
}
}
实际项目中的应用
// 数据库访问抽象工厂示例
interface Connection {
void connect();
}
interface Statement {
void execute(String sql);
}
// MySQL实现
class MySQLConnection implements Connection {
@Override
public void connect() {
System.out.println("连接MySQL数据库");
}
}
class MySQLStatement implements Statement {
@Override
public void execute(String sql) {
System.out.println("MySQL执行SQL: " + sql);
}
}
// PostgreSQL实现
class PostgreSQLConnection implements Connection {
@Override
public void connect() {
System.out.println("连接PostgreSQL数据库");
}
}
class PostgreSQLStatement implements Statement {
@Override
public void execute(String sql) {
System.out.println("PostgreSQL执行SQL: " + sql);
}
}
// 数据库抽象工厂
interface DatabaseFactory {
Connection createConnection();
Statement createStatement();
}
// MySQL工厂
class MySQLFactory implements DatabaseFactory {
@Override
public Connection createConnection() {
return new MySQLConnection();
}
@Override
public Statement createStatement() {
return new MySQLStatement();
}
}
// PostgreSQL工厂
class PostgreSQLFactory implements DatabaseFactory {
@Override
public Connection createConnection() {
return new PostgreSQLConnection();
}
@Override
public Statement createStatement() {
return new PostgreSQLStatement();
}
}
// 数据库访问类
class DatabaseAccess {
private Connection connection;
private Statement statement;
public DatabaseAccess(DatabaseFactory factory) {
connection = factory.createConnection();
statement = factory.createStatement();
}
public void executeQuery(String sql) {
connection.connect();
statement.execute(sql);
}
}
// 使用示例
public class DatabaseFactoryDemo {
public static void main(String[] args) {
// 使用MySQL
DatabaseFactory mysqlFactory = new MySQLFactory();
DatabaseAccess mysqlAccess = new DatabaseAccess(mysqlFactory);
mysqlAccess.executeQuery("SELECT * FROM users");
System.out.println();
// 使用PostgreSQL
DatabaseFactory postgresFactory = new PostgreSQLFactory();
DatabaseAccess postgresAccess = new DatabaseAccess(postgresFactory);
postgresAccess.executeQuery("SELECT * FROM users");
}
}
总结
抽象工厂模式是一种强大的创建型设计模式,它通过提供一个创建一系列相关或相互依赖对象的接口,实现了产品族的一致性和系统的可扩展性。在实际开发中,当我们需要创建一组相关的产品对象,并且希望保持这些产品之间的一致性时,抽象工厂模式是一个很好的选择。
使用抽象工厂模式的关键点:
- 识别出需要创建的产品具有多个等级结构,并且这些产品之间存在关联关系
- 将相关的产品组织成产品族,每个产品族对应一个具体工厂
- 通过抽象工厂接口统一管理产品族的创建过程
- 客户端通过抽象工厂接口来使用具体工厂,而不需要关心具体产品的创建细节
需要注意的是,抽象工厂模式虽然提供了良好的扩展性,但在产品等级结构发生变化时,修改成本较高。因此,在使用抽象工厂模式时,需要仔细考虑产品的稳定性和变化频率。