​​抽象工厂模式(Abstract Factory Pattern)​​

定义

抽象工厂模式是一种创建型设计模式,​​提供一组相关或依赖对象的创建接口,而无需指定具体类​​。它强调创建​​产品族​​(一组相关联的产品),例如不同操作系统的 UI 组件(按钮、文本框等),或不同数据库的驱动适配器。

UML 类图​

设计模式之创建型:抽象工厂模式_抽象工厂

  • ​​AbstractFactory(抽象工厂)​​​:声明创建​​一组产品​​的接口(如 createProductA() 和 createProductB())。
  • ​​ConcreteFactory(具体工厂)​:实现抽象工厂接口,创建属于同一产品族的具体产品(如 ConcreteFactory1 创建 ProductA1 和 ProductB1)。
  • AbstractProduct(抽象产品)​​​:定义一类产品的接口(如 AbstractProductA 和 AbstractProductB)。
  • ​​ConcreteProduct(具体产品)​​:实现抽象产品接口的具体类(如 ConcreteProductA1 属于产品族 1)。

优点​

  • 产品族一致性​​:确保创建的对象属于同一系列(例如同一操作系统下的所有 UI 组件)。
  • 客户端与实现解耦​​:客户端代码仅依赖抽象接口,不依赖具体类。
  • 开闭原则​​:新增产品族时,只需添加新的具体工厂和产品类,无需修改已有代码。
  • 单一职责原则​​:每个工厂类只负责创建特定产品族。

缺点​​

  • 扩展新产品类型困难​​:若需在已有产品族中添加新类型(如新增 AbstractProductC),需修改所有抽象工厂和具体工厂,违反开闭原则。
  • ​​类数量膨胀​​:每新增一个产品族需新增多个类(工厂 + 产品),增加系统复杂度。
  • ​​理解成本高​​:多层抽象和依赖关系对新手不够友好。

适用场景​

  • 跨平台应用​​:需要为不同操作系统(如 Windows、macOS)生成配套的 UI 组件或服务。
  • 数据库适配器​​:为不同数据库(MySQL、PostgreSQL)创建连接、查询等兼容对象。
  • ​​主题系统​​:提供一套主题相关的组件(如暗黑/明亮主题的按钮、字体、颜色)。
  • ​​产品族约束​​:要求一组对象必须一起使用,且需屏蔽具体实现细节。

案例

UML 类图​

设计模式之创建型:抽象工厂模式_抽象工厂_02

Factory

public interface Factory {

}
  • 1.
  • 2.
  • 3.

ComputerProductFactory

/**
 * ComputerProductFactory
 */
public interface ComputerProductFactory extends Factory {
	
	MouseProduct createMouseProduct();
	
	KeyboardProduct createKeyboardProduct();
	
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

Product

/**
 * 产品标准
 */
public interface Product {

    /**
     * 获取产品名称
     * @return 产品名称
     */
    String getName();

}

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

KeyboardProduct

/**
 * 键盘
 */
public interface KeyboardProduct extends Product {
	
}

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

MouseProduct

/**
 * 鼠标
 */
public interface MouseProduct extends Product {
	
}

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

LenovoComputerProductFactory

/**
 * 联想计算机外设工厂
 */
public class LenovoComputerProductFactory implements ComputerProductFactory {
	
	@Override
	public MouseProduct createMouseProduct() {
		return new LenovoMouseProduct();
	}
	
	@Override
	public KeyboardProduct createKeyboardProduct() {
		return new LenovoKeyboardProduct();
	}
}

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

LenovoKeyboardProduct

/**
 * LenovoKeyboardProduct
 *
 */
public class LenovoKeyboardProduct implements KeyboardProduct {
	@Override
	public String getName() {
		return "我是联想键盘";
	}
}

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

LenovoMouseProduct

/**
 * LenovoMouseProduct
 */
public class LenovoMouseProduct implements MouseProduct {
	@Override
	public String getName() {
		return "我是联想鼠标";
	}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

LogitechComputerProductFactory

/**
 * 罗技计算机外设工厂
 */
public class LogitechComputerProductFactory implements ComputerProductFactory {
	@Override
	public MouseProduct createMouseProduct() {
		return new LogitechMouseProduct();
	}
	
	@Override
	public KeyboardProduct createKeyboardProduct() {
		return new LogitechKeyboardProduct();
	}
}

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

LogitechKeyboardProduct

/**
 * LogitechKeyboardProduct
 */
public class LogitechKeyboardProduct implements KeyboardProduct {
	@Override
	public String getName() {
		return "我是罗技键盘";
	}
}


  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

LogitechMouseProduct

/**
 * LogitechMouseProduct
 */
public class LogitechMouseProduct implements MouseProduct {
	@Override
	public String getName() {
		return "我是罗技鼠标";
	}
}

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

Client

/**
 * 想要鼠标和键盘套装,
 * 联想套装
 * 罗技套装
 */
public class Client {

    public static void main(String[] args) {

        ComputerProductFactory lenovoFactory = new LenovoComputerProductFactory();
        MouseProduct lenovoMouse = lenovoFactory.createMouseProduct();
        KeyboardProduct lenovoKeyboard = lenovoFactory.createKeyboardProduct();
        System.out.println(lenovoMouse.getName());
        System.out.println(lenovoKeyboard.getName());

        LogitechComputerProductFactory logitechFactory = new LogitechComputerProductFactory();
        MouseProduct logitechMouse = logitechFactory.createMouseProduct();
        KeyboardProduct logitechKeyboard = logitechFactory.createKeyboardProduct();
        System.out.println(logitechMouse.getName());
        System.out.println(logitechKeyboard.getName());

    }

}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.

抽象工厂模式 vs 工厂方法模式

对比维度抽象工厂模式工厂方法模式
核心目标创建多个相关产品族(如跨平台UI组件套件)创建单个产品类型(如不同格式的日志记录器)
产品结构包含多个产品等级结构(如Button+TextBox)仅一个产品等级结构(如Document)
产品关系强调产品间的兼容性(必须属于同一系列)不要求产品间有关联性
工厂职责一个工厂创建多种产品(多方法)一个工厂创建一种产品(单方法)
扩展方向扩展产品族容易(新增ConcreteFactory)
扩展产品类型困难(需改接口)
扩展产品类型容易(新增ConcreteCreator)
适用场景需要保证产品兼容性(如操作系统、主题套件)需要灵活扩展单一产品类型(如文件格式)
类数量复杂度高(工厂+多产品类)低(工厂+单产品类)
开闭原则对新增产品族开放,对新增产品类型关闭对新增产品类型开放

关键差异总结
  1. 目标不同

    • 抽象工厂:解决多系列产品兼容性问题(如 Windows/macOS 整套组件)。
    • 工厂方法:解决单一产品多态化创建问题(如 PDF/Word 文档生成)。
  2. 扩展性差异

    • 抽象工厂新增产品族时只需添加新工厂类(如 MacOSFactory),但新增产品类型需修改所有工厂接口。
    • 工厂方法新增产品类型时只需添加新子类(如 ExcelDocument),无需修改已有代码。
  3. 复杂度差异

    • 抽象工厂需要管理多个产品层级,适合中大型系统。
    • 工厂方法结构简单,适合单一产品扩展场景。

选择建议
  • 使用抽象工厂:当系统需要一组相互依赖的对象(如 UI 组件 + 字体 + 颜色)。
  • 使用工厂方法:当系统需要灵活扩展单一产品类型(如不同数据库驱动)。