概述
抽象工厂模式(Abstract Factory Pattern)是创建型设计模式的高级形态,是对工厂方法模式的进一步扩展。其核心目标是提供一个创建一系列相互依赖或关联的产品族的接口,客户端无需指定具体产品类,仅需通过抽象工厂的具体实现类,即可获取一整套相关联的产品实例,实现产品族的整体切换。
该模式将“产品族”与“工厂”绑定,每个具体工厂负责创建一组配套产品,既保持了工厂方法模式的“开放-封闭原则”,又解决了多类关联产品的创建和解耦问题,适用于复杂业务场景中多产品协同工作的需求。
核心价值
| 核心要点 |
详细说明 |
| 产品族整体封装 |
将相互关联的产品(如“手机+电脑”“支付+退款”)打包创建,确保产品族内组件的兼容性,避免客户端手动组合导致的逻辑错误 |
| 支持整体切换 |
切换具体工厂即可实现产品族的整体替换(如从“华为产品族”切换到“苹果产品族”),无需修改客户端调用逻辑 |
| 解耦更彻底 |
客户端仅依赖抽象工厂和抽象产品接口,与具体实现完全分离,修改产品实现或新增产品族时不影响客户端 |
| 遵循开闭原则 |
新增产品族时,仅需新增对应的抽象产品接口(如需)和具体工厂类,无需修改原有工厂和产品代码 |
| 职责边界清晰 |
每个具体工厂仅负责创建对应产品族的组件,产品族内的关联逻辑封装在工厂中,提升代码可维护性 |
适用场景
| 场景类型 |
具体说明 |
| 多产品族协同场景 |
业务中存在多组相互关联的产品(产品族),如电子设备(手机+电脑+平板)、支付系统(支付+退款+对账)、物流系统(下单+查询+取消) |
| 产品族整体切换场景 |
需支持产品族动态切换,如电商平台切换“品牌供应商”(切换后所有配套产品同步替换)、项目切换“技术栈组件”(如日志+缓存+数据库组件整体替换) |
| 复杂产品依赖场景 |
产品之间存在强依赖关系(如“数据库连接+查询器”“缓存客户端+序列化工具”),需确保依赖产品的兼容性 |
| 中大型项目架构设计 |
大型项目需规范化组件创建逻辑,避免零散的对象实例化导致的耦合,抽象工厂模式可作为组件创建的统一标准 |
注意事项
| 注意点 |
具体说明 |
| 避免过度设计 |
若仅需创建单一产品(无关联产品),或产品族极少且无扩展计划,使用工厂方法模式或简单工厂模式更简洁 |
| 新增单一产品成本高 |
若需在现有产品族中新增单个产品(非产品族整体扩展),需修改抽象工厂接口和所有具体工厂类,违背开闭原则 |
| 类结构复杂度提升 |
相比工厂方法模式,抽象工厂模式需定义更多抽象接口和具体类(产品族+工厂),需合理规划类结构避免冗余 |
| 依赖抽象接口 |
客户端必须依赖抽象工厂和抽象产品接口,而非具体实现类,否则会失去解耦意义,导致扩展困难 |
完整代码
以“电子设备产品族”为业务场景,存在两个产品族(华为产品族、苹果产品族),每个产品族包含“手机”和“电脑”两个关联产品,通过抽象工厂模式实现产品族的统一创建和切换。
<?php
declare(strict_types = 1);
/**
* 抽象产品接口1:手机产品规范
*/
interface PhoneProductInterface
{
public function call(): string;
public function getBrand(): string;
}
/**
* 抽象产品接口2:电脑产品规范
*/
interface ComputerProductInterface
{
public function work(): string;
public function getBrand(): string;
}
/**
* 具体产品1-1:华为手机(华为产品族)
*/
class HuaweiPhone implements PhoneProductInterface
{
public function call(): string
{
return "华为手机:支持5G高清通话、鸿蒙生态互联";
}
public function getBrand(): string
{
return "华为";
}
}
/**
* 具体产品1-2:华为电脑(华为产品族)
*/
class HuaweiComputer implements ComputerProductInterface
{
public function work(): string
{
return "华为电脑:多屏协同、高性能处理器、鸿蒙OS";
}
public function getBrand(): string
{
return "华为";
}
}
/**
* 具体产品2-1:苹果手机(苹果产品族)
*/
class ApplePhone implements PhoneProductInterface
{
public function call(): string
{
return "苹果手机:Face ID解锁、iOS生态联动、高清通话";
}
public function getBrand(): string
{
return "苹果";
}
}
/**
* 具体产品2-2:苹果电脑(苹果产品族)
*/
class AppleComputer implements ComputerProductInterface
{
public function work(): string
{
return "苹果电脑:M系列芯片、macOS系统、生态协同";
}
public function getBrand(): string
{
return "苹果";
}
}
/**
* 抽象工厂接口:定义产品族的创建规范(需创建手机和电脑)
*/
interface DeviceFactoryInterface
{
public function createPhone(): PhoneProductInterface;
public function createComputer(): ComputerProductInterface;
}
/**
* 具体工厂1:华为工厂(创建华为产品族)
*/
class HuaweiFactory implements DeviceFactoryInterface
{
public function createPhone(): PhoneProductInterface
{
// 华为手机专属初始化逻辑(如加载硬件配置、初始化系统)
$this->initHuaweiDeviceConfig();
return new HuaweiPhone();
}
public function createComputer(): ComputerProductInterface
{
$this->initHuaweiDeviceConfig();
return new HuaweiComputer();
}
/**
* 华为产品族统一初始化逻辑
*/
private function initHuaweiDeviceConfig(): void
{
// 模拟加载华为设备通用配置(如服务器地址、生态密钥)
// $config = require_once 'huawei_config.php';
}
}
/**
* 具体工厂2:苹果工厂(创建苹果产品族)
*/
class AppleFactory implements DeviceFactoryInterface
{
public function createPhone(): PhoneProductInterface
{
// 苹果设备专属初始化逻辑(如加载证书、初始化生态服务)
$this->initAppleEcosystem();
return new ApplePhone();
}
public function createComputer(): ComputerProductInterface
{
$this->initAppleEcosystem();
return new AppleComputer();
}
/**
* 苹果产品族统一初始化逻辑
*/
private function initAppleEcosystem(): void
{
// 模拟加载苹果生态配置(如App Store接口、iCloud服务配置)
// $config = require_once 'apple_config.php';
}
}
// 测试代码
try {
// 1. 使用华为工厂创建华为产品族
echo "=== 华为产品族 ===" . PHP_EOL;
$huaweiFactory = new HuaweiFactory();
$huaweiPhone = $huaweiFactory->createPhone();
$huaweiComputer = $huaweiFactory->createComputer();
echo $huaweiPhone->getBrand() . ":" . $huaweiPhone->call() . PHP_EOL;
echo $huaweiComputer->getBrand() . ":" . $huaweiComputer->work() . PHP_EOL . PHP_EOL;
// 2. 使用苹果工厂创建苹果产品族(切换产品族仅需替换工厂)
echo "=== 苹果产品族 ===" . PHP_EOL;
$appleFactory = new AppleFactory();
$applePhone = $appleFactory->createPhone();
$appleComputer = $appleFactory->createComputer();
echo $applePhone->getBrand() . ":" . $applePhone->call() . PHP_EOL;
echo $appleComputer->getBrand() . ":" . $appleComputer->work() . PHP_EOL;
// 3. 动态切换产品族(如根据配置文件选择工厂)
$factoryType = 'huawei'; // 可从配置或数据库读取
$factory = match ($factoryType) {
'huawei' => new HuaweiFactory(),
'apple' => new AppleFactory(),
default => throw new \InvalidArgumentException("不支持的产品族类型"),
};
echo PHP_EOL . "=== 动态切换产品族(" . $factoryType . ") ===" . PHP_EOL;
echo $factory->createPhone()->call() . PHP_EOL;
} catch (\Exception $e) {
echo "错误:" . $e->getMessage();
}
核心设计说明
1. 核心结构拆解
// 1. 抽象产品接口(产品族的组件规范)
// 手机产品规范
interface PhoneProductInterface { /* 统一方法定义 */ }
// 电脑产品规范
interface ComputerProductInterface { /* 统一方法定义 */ }
// 2. 具体产品类(产品族的具体实现)
// 华为产品族组件
class HuaweiPhone implements PhoneProductInterface { /* 业务逻辑 */ }
class HuaweiComputer implements ComputerProductInterface { /* 业务逻辑 */ }
// 苹果产品族组件
class ApplePhone implements PhoneProductInterface { /* 业务逻辑 */ }
class AppleComputer implements ComputerProductInterface { /* 业务逻辑 */ }
// 3. 抽象工厂接口(产品族的创建规范)
interface DeviceFactoryInterface
{
public function createPhone(): PhoneProductInterface; // 创建产品族组件1
public function createComputer(): ComputerProductInterface; // 创建产品族组件2
}
// 4. 具体工厂类(产品族的创建实现)
class HuaweiFactory implements DeviceFactoryInterface
{
public function createPhone(): PhoneProductInterface { return new HuaweiPhone(); }
public function createComputer(): ComputerProductInterface { return new HuaweiComputer(); }
}
2. 关键优化点(对比工厂方法模式)
// 优化1:支持产品族创建,而非单一产品
// 抽象工厂接口定义多个产品创建方法,对应一组关联产品
interface DeviceFactoryInterface
{
public function createPhone(): PhoneProductInterface;
public function createComputer(): ComputerProductInterface;
}
// 优化2:产品族内统一初始化,确保兼容性
// 具体工厂封装产品族的通用初始化逻辑,所有组件共享配置
private function initHuaweiDeviceConfig(): void
{
// 产品族通用配置加载,避免组件各自初始化导致的不一致
}
// 优化3:产品族整体切换,客户端无感知
// 切换工厂即切换整个产品族,无需修改产品调用逻辑
$factory = new HuaweiFactory(); // 切换为 AppleFactory 即可换产品族
$phone = $factory->createPhone();
$computer = $factory->createComputer();
// 优化4:抽象产品接口细分,职责更明确
// 不同类型产品(手机、电脑)定义独立接口,避免单一接口过于臃肿
interface PhoneProductInterface { /* 手机专属方法 */ }
interface ComputerProductInterface { /* 电脑专属方法 */ }
3. 常见错误规避
// 错误1:抽象工厂接口定义单一产品创建方法,沦为工厂方法模式
// 解决:抽象工厂需定义一组关联产品的创建方法,对应产品族的所有组件
interface DeviceFactoryInterface
{
public function createPhone(): PhoneProductInterface;
public function createComputer(): ComputerProductInterface; // 必须包含产品族所有组件
}
// 错误2:具体工厂创建非对应产品族的组件(如华为工厂创建苹果手机)
// 解决:严格遵循“工厂-产品族”绑定规则,一个具体工厂仅创建对应产品族的组件
class HuaweiFactory implements DeviceFactoryInterface
{
public function createPhone(): PhoneProductInterface
{
return new HuaweiPhone(); // 仅创建华为产品族组件
}
}
// 错误3:客户端直接依赖具体产品或工厂,耦合度高
// 解决:客户端仅依赖抽象接口,通过工厂接口获取产品
$factory = new HuaweiFactory(); // 可替换为 AppleFactory
$phone = $factory->createPhone(); // 依赖 PhoneProductInterface,不依赖具体产品
// 错误4:产品族内组件无统一初始化逻辑,导致兼容性问题
// 解决:在具体工厂中封装产品族通用初始化逻辑,所有组件创建前执行
private function initHuaweiDeviceConfig(): void
{
// 产品族通用配置(如生态密钥、服务器地址)
}
补充说明
1. 扩展场景示例(新增产品族)
若需新增“小米产品族”(包含小米手机、小米电脑),仅需新增具体产品类和具体工厂类,无需修改原有代码,完全遵循开闭原则:
// 1. 新增小米产品族具体产品
class XiaomiPhone implements PhoneProductInterface
{
public function call(): string
{
return "小米手机:MIUI系统、快充技术、生态联动";
}
public function getBrand(): string
{
return "小米";
}
}
class XiaomiComputer implements ComputerProductInterface
{
public function work(): string
{
return "小米电脑:高性价比、MIUI+互联、Windows系统";
}
public function getBrand(): string
{
return "小米";
}
}
// 2. 新增小米工厂(实现抽象工厂接口)
class XiaomiFactory implements DeviceFactoryInterface
{
public function createPhone(): PhoneProductInterface
{
$this->initXiaomiConfig();
return new XiaomiPhone();
}
public function createComputer(): ComputerProductInterface
{
$this->initXiaomiConfig();
return new XiaomiComputer();
}
private function initXiaomiConfig(): void
{
// 小米产品族通用初始化逻辑
}
}
// 客户端使用(无需修改原有代码)
echo PHP_EOL . "=== 小米产品族 ===" . PHP_EOL;
$xiaomiFactory = new XiaomiFactory();
echo $xiaomiFactory->createPhone()->call() . PHP_EOL;
echo $xiaomiFactory->createComputer()->work() . PHP_EOL;
2. 实际应用场景
| 场景分类 |
具体说明 |
| 多品牌组件套装 |
如不同品牌的“智能家居套装”(灯光+窗帘+空调)、“办公设备套装”(打印机+扫描仪+投影仪),每个品牌对应一个产品族 |
| 框架技术栈切换 |
如项目支持多数据库驱动(MySQL+Redis+Elasticsearch),不同数据库对应一个产品族,切换数据库时整体替换所有组件 |
| 支付系统多渠道 |
如支付渠道的“支付+退款+对账+通知”组合,每个支付渠道(支付宝/微信/银联)对应一个产品族,确保流程一致性 |
| 跨平台应用开发 |
如跨平台APP的“UI组件+API适配”组合,每个平台(iOS/Android/Windows)对应一个产品族,统一创建平台适配组件 |
3. 三种工厂模式核心区别对比表
| 对比维度 |
简单工厂模式 |
工厂方法模式 |
抽象工厂模式 |
| 核心结构 |
单一静态工厂类 + 多个具体产品(无抽象工厂) |
抽象工厂接口 + 多个具体工厂(一对一) + 多个具体产品 |
抽象工厂接口 + 多个具体工厂(一对多) + 多组抽象产品+具体产品 |
| 产品创建范围 |
单一类型产品(无关联) |
单一类型产品(无关联) |
一组相互关联的产品族 |
| 开闭原则 |
不遵循:新增产品需修改工厂类判断逻辑 |
遵循:新增产品仅需新增产品类和工厂子类 |
部分遵循:新增产品族遵循,新增单一产品不遵循 |
| 类数量 |
少(1个工厂类) |
中(1个抽象工厂+N个具体工厂+N个产品) |
多(M个抽象产品+N个具体产品+1个抽象工厂+K个具体工厂) |
| 客户端依赖 |
依赖具体工厂类 + 抽象产品 |
依赖抽象工厂接口 + 抽象产品 |
依赖抽象工厂接口 + 多组抽象产品 |
| 灵活性 |
低:切换产品需修改参数 |
中:切换产品需替换工厂子类 |
高:切换产品族仅需替换工厂子类 |
| 适用场景 |
产品少、变动少,追求简洁 |
产品多、需扩展,单一类型产品 |
多产品族、需整体切换,关联产品协同 |
| 扩展成本 |
低(修改工厂类) |
中(新增2个类) |
新增产品族低(新增K+M个类),新增单一产品高(修改所有工厂) |