陈大剩博客

php设计模式(四):抽象工厂(Abstract Factory)

  • 陈大剩
  • 2023-04-13 09:13:03
  • 747

抽象工厂

抽象工厂(Abstract Factory)是一种创建型设计模式,它能创建一系列相关的对象,而无需指定其具体类

问题

假设你需要开发一款组装DIY台式电脑的应用,最初只需要拼装一台台式电脑并计算出每台总部件价格即可(简单工厂方法),现在需要组装成品牌机(华硕、联想、…),对于品牌机每个部件都需要属于这个品牌。

通过工厂方法我们需要创建很多的产品工厂类,而且你不留神,可能会给顾客组装错误的部件,如华硕的台式机组装了联想的键盘,这样如果顾客收到的部件不一样,他们会心里万只草泥马。

此外, 你也不希望在添加新部件或新品牌时修改已有代码。品牌机供应对于产品目录的更新非常频繁,你不会想在每次更新时都去修改核心代码的。

解决方法

STEP 1 建立产品

抽象工厂模式为系列中的每个部件明确声明接口(例如键盘、鼠标或显示器)。然后,确保所有部件变体都继承这些接口。例如,所有品牌的鼠标都实现 鼠标 接口;所有品牌的键盘都实现 键盘 接口,以此类推。

STEP 2 声明抽象工厂

声明抽象工厂。例如 createMouse 创建鼠标 、 createKeyboard 创建键盘 和 createDisplay 创建显示器 。 这些方法必须返回抽象产品类型,即我们之前抽取的那些接口: 鼠标 ,沙发 和 显示器 等等。

STEP 3 创建具体工厂

创建具体品牌工厂。例如 AsusComputerAbstractFactory 华硕台式电脑工厂,实现 STEP 2 声明抽象工厂 抽象工厂类接口。

STEP 4 客户端使用

客户端直接使用STEP 3 创建具体品牌工厂具体的工厂即可,无需知道部件是什么品牌。

结构

多个 interface 或者 abstract 产品基类
多个实现 interface 或者继承 abstract 的具体产品类

1个 interface 或者 abstract 工厂基类
1个实现 interface 或者继承 abstract 的具体工厂类

具体的工厂类里面有多个方法分别实例化具体的产品类

代码示例

抽象产品基类

// Keyboard.php
interface Keyboard
{
    public function getPrice();
}

// Mouse.php
interface Mouse
{
    public function getPrice();
}

具体产品

华硕电脑


// AsusMouse.php
class AsusMouse implements Mouse
{
    public function getPrice(): float
    {
        return 49.9;
    }
}

// AsusKeyboard.php
class AsusKeyboard implements Keyboard
{
    public function getPrice(): float
    {
        return 149.9;
    }
}

...

产品工厂类基类

// AbstractFactory.php
interface AbstractFactory
{
    public function createKeyboard();

    public function createMouse();
}

产品工具体厂类

// AsusComputerAbstractFactory.php
class AsusComputerAbstractFactory implements AbstractFactory
{
    public function createKeyboard(): Product
    {
        return new AsusKeyboard();
    }

    public function createMouse(): Product
    {
        return new AsusMouse();
    }
    
    ...
}

客户端类

// Client.php
// 华硕工厂类
$asusComputer = new AsusComputerAbstractFactory();

// 鼠标
$mouse = $asusComputer->createMouse();
$mousePrice = $mouse->getPrice();

// 键盘
$keyboard = $asusComputer->createKeyboard();
$keyboardPrice = $keyboard->getPrice();
...

echo $mousePrice + $keyboardPrice + ...;

UML

UML

代码

抽象工厂模式代码

优缺点

优点

  • 你可以确保同一工厂生成的产品相互匹配。
  • 你可以避免客户端和具体产品代码的耦合。
  • 单一职责原则。 你可以将产品生成代码抽取到同一位置, 使得代码易于维护。
  • 开闭原则。 向应用程序中引入新产品变体时, 你无需修改客
    户端代码。

缺点

  • 工厂需要引入很多新的子类,代码可能会因此变得更复杂。
分享到:
0

说点儿什么吧

头像

表情

本站由陈大剩博客程序搭建 | 湘ICP备2023000975号| Copyright © 2017 - 陈大剩博客 | 本站采用创作共用版权:CC BY-NC 4.0

站长统计| 文章总数[115]| 评论总数[9]| 登录用户[22]| 时间点[118]

logo

登入

社交账号登录