创建型设计模式-抽象工厂 Abstract Factory
Tags: 设计模式, designpatterns
Published: 2023-09-06 03:37:45



### 简介

拿工厂方法模式作对比，在工厂方法模式中，一个工厂只能创建一种产品，如椅子工厂只能创建椅子。而抽象工厂可以创建一系列产品，如家具工厂可以创建椅子，桌子，床等等。

抽象工厂类负责定义可以创建的抽象产品类，具体工厂编写不同风格（即各自的业务逻辑）的创建产品的过程。

### 角色

- 抽象工厂
    
    定义工厂可以生产的抽象产品，多个产品则对应多个创建方法
    
- 抽象产品
    
    与工厂方法模式中没什么区别，简单定义类属性即可
    
    可能有多个，抽象椅子，抽象桌子，抽象床等
    
- 具体工厂
    
    分别实现抽象工厂中定义的创建产品的方法
    
    可能有多个，按照不同风格或叫不同业务逻辑，创建一组产品，如古典工厂创建古典风格椅子、桌子、床，现代工厂创建现代风格桌椅床。
    
- 具体产品
    
    实现抽象产品即可
    
    可能有多个，现代风格桌子、古典风格椅子等等
    

### 类图

图中展示，GUIFactory 抽象工厂定义可以创建 Button 和 Checkbox 抽象产品。

具体工厂WinFactory可以创建出 Win 风格的 WinButton 和 WinCheckbox，MacFatory 可以创建出 Mac 风格的 MacButton 和 MacCheckbox。

![类图](https://deb-gmi.oss-cn-beijing.aliyuncs.com/img/20210408165956.png)

### 代码

```php
interface AbstractFactory
{
    public function createProductA(): AbstractProductA;

    public function createProductB(): AbstractProductB;
}

class ConcreteFactory1 implements AbstractFactory
{
    public function createProductA(): AbstractProductA
    {
        return new ConcreteProductA1();
    }

    public function createProductB(): AbstractProductB
    {
        return new ConcreteProductB1();
    }
}

class ConcreteFactory2 implements AbstractFactory
{
    public function createProductA(): AbstractProductA
    {
        return new ConcreteProductA2();
    }

    public function createProductB(): AbstractProductB
    {
        return new ConcreteProductB2();
    }
}

interface AbstractProductA
{
    public function usefulFunctionA(): string;
}

class ConcreteProductA1 implements AbstractProductA
{
    public function usefulFunctionA(): string
    {
        return "The result of the product A1.";
    }
}

class ConcreteProductA2 implements AbstractProductA
{
    public function usefulFunctionA(): string
    {
        return "The result of the product A2.";
    }
}

interface AbstractProductB
{
    public function usefulFunctionB(): string;

    public function anotherUsefulFunctionB(AbstractProductA $collaborator): string;
}

class ConcreteProductB1 implements AbstractProductB
{
    public function usefulFunctionB(): string
    {
        return "The result of the product B1.";
    }

    public function anotherUsefulFunctionB(AbstractProductA $collaborator): string
    {
        $result = $collaborator->usefulFunctionA();

        return "The result of the B1 collaborating with the ({$result})";
    }
}

class ConcreteProductB2 implements AbstractProductB
{
    public function usefulFunctionB(): string
    {
        return "The result of the product B2.";
    }

    public function anotherUsefulFunctionB(AbstractProductA $collaborator): string
    {
        $result = $collaborator->usefulFunctionA();

        return "The result of the B2 collaborating with the ({$result})";
    }
}

function clientCode(AbstractFactory $factory)
{
    $productA = $factory->createProductA();
    $productB = $factory->createProductB();

    echo $productB->usefulFunctionB() . "\n";
    echo $productB->anotherUsefulFunctionB($productA) . "\n";
}

echo "Client: Testing client code with the first factory type:\n";
clientCode(new ConcreteFactory1());

echo "Client: Testing the same client code with the second factory type:\n";
clientCode(new ConcreteFactory2());
```

output:

```
Client: Testing client code with the first factory type:
The result of the product B1.
The result of the B1 collaborating with the (The result of the product A1.)
Client: Testing the same client code with the second factory type:
The result of the product B2.
The result of the B2 collaborating with the (The result of the product A2.)
```