1.8. Static Factory

1.8.1. Purpose

Similar to the AbstractFactory, this pattern is used to create series of related or dependent objects. The difference between this and the abstract factory pattern is that the static factory pattern uses just one static method to create all types of objects it can create. It is usually named factory or build.

1.8.2. UML Diagram

Alt StaticFactory UML Diagram

1.8.3. Code

You can also find this code on 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. Test

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}