PHP 抽象工厂模式

概述

抽象工厂模式(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个类),新增单一产品高(修改所有工厂)