1.8. 静态工厂

1.8.1. 目的

与 抽象工厂 类似,静态工厂模式用于创建一系列互相关联或依赖的对象。它与抽象工厂模式的区别在于,静态工厂模式仅使用 一个静态方法 来创建所有它可以创建的类型。通常,这个静态方法被命名为:factorybuild

1.8.2. UML 图

Alt StaticFactory UML Diagram

1.8.3. 代码

你可以在 GitHub 上找到这些代码

StaticFactory.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\StaticFactory;
 6
 7use InvalidArgumentException;
 8
 9/**
10 * Note1: Remember, static means global state which is evil because it can't be mocked for tests
11 * Note2: Cannot be subclassed or mock-upped or have multiple different instances.
12 */
13final class StaticFactory
14{
15    public static function factory(string $type): Formatter
16    {
17        return match ($type) {
18            'number' => new FormatNumber(),
19            'string' => new FormatString(),
20            default => throw new InvalidArgumentException('Unknown format given'),
21        };
22    }
23}

Formatter.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\StaticFactory;
 6
 7interface Formatter
 8{
 9    public function format(string $input): string;
10}

FormatString.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\StaticFactory;
 6
 7class FormatString implements Formatter
 8{
 9    public function format(string $input): string
10    {
11        return $input;
12    }
13}

FormatNumber.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\StaticFactory;
 6
 7class FormatNumber implements Formatter
 8{
 9    public function format(string $input): string
10    {
11        return number_format((int) $input);
12    }
13}

1.8.4. 测试

Tests/StaticFactoryTest.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\StaticFactory\Tests;
 6
 7use InvalidArgumentException;
 8use DesignPatterns\Creational\StaticFactory\FormatNumber;
 9use DesignPatterns\Creational\StaticFactory\FormatString;
10use DesignPatterns\Creational\StaticFactory\StaticFactory;
11use PHPUnit\Framework\TestCase;
12
13class StaticFactoryTest extends TestCase
14{
15    public function testCanCreateNumberFormatter()
16    {
17        $this->assertInstanceOf(FormatNumber::class, StaticFactory::factory('number'));
18    }
19
20    public function testCanCreateStringFormatter()
21    {
22        $this->assertInstanceOf(FormatString::class, StaticFactory::factory('string'));
23    }
24
25    public function testException()
26    {
27        $this->expectException(InvalidArgumentException::class);
28
29        StaticFactory::factory('object');
30    }
31}