1.3. Метод Фабрика

1.3.1. Предназначение

Добрата точка за SimpleFactory е, че можете да го подкласирате, за да реализира различни начини за създаване на обекти.

За прости случаи този абстрактен клас може да бъде просто интерфейс.

Този модел е „истински“ шаблон на проектиране, тъй като постига принципа на инверсия на зависимостите, известен още като „D“ в SOLID принципите.

Това означава, че класът FactoryMethod зависи от абстракциите, а не от конкретни класове. Това е истинският трик в сравнение с SimpleFactory или StaticFactory.

1.3.2. UML Диаграма

Alt FactoryMethod UML Diagram

1.3.3. Код

Можете също да намерите този код в GitHub

Logger.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\FactoryMethod;
 6
 7interface Logger
 8{
 9    public function log(string $message);
10}

StdoutLogger.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\FactoryMethod;
 6
 7class StdoutLogger implements Logger
 8{
 9    public function log(string $message)
10    {
11        echo $message;
12    }
13}

FileLogger.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\FactoryMethod;
 6
 7class FileLogger implements Logger
 8{
 9    public function __construct(private string $filePath)
10    {
11    }
12
13    public function log(string $message)
14    {
15        file_put_contents($this->filePath, $message . PHP_EOL, FILE_APPEND);
16    }
17}

LoggerFactory.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\FactoryMethod;
 6
 7interface LoggerFactory
 8{
 9    public function createLogger(): Logger;
10}

StdoutLoggerFactory.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\FactoryMethod;
 6
 7class StdoutLoggerFactory implements LoggerFactory
 8{
 9    public function createLogger(): Logger
10    {
11        return new StdoutLogger();
12    }
13}

FileLoggerFactory.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\FactoryMethod;
 6
 7class FileLoggerFactory implements LoggerFactory
 8{
 9    public function __construct(private string $filePath)
10    {
11    }
12
13    public function createLogger(): Logger
14    {
15        return new FileLogger($this->filePath);
16    }
17}

1.3.4. Тест

Tests/FactoryMethodTest.php

 1<?php
 2
 3declare(strict_types=1);
 4
 5namespace DesignPatterns\Creational\FactoryMethod\Tests;
 6
 7use DesignPatterns\Creational\FactoryMethod\FileLogger;
 8use DesignPatterns\Creational\FactoryMethod\FileLoggerFactory;
 9use DesignPatterns\Creational\FactoryMethod\StdoutLogger;
10use DesignPatterns\Creational\FactoryMethod\StdoutLoggerFactory;
11use PHPUnit\Framework\TestCase;
12
13class FactoryMethodTest extends TestCase
14{
15    public function testCanCreateStdoutLogging()
16    {
17        $loggerFactory = new StdoutLoggerFactory();
18        $logger = $loggerFactory->createLogger();
19
20        $this->assertInstanceOf(StdoutLogger::class, $logger);
21    }
22
23    public function testCanCreateFileLogging()
24    {
25        $loggerFactory = new FileLoggerFactory(sys_get_temp_dir());
26        $logger = $loggerFactory->createLogger();
27
28        $this->assertInstanceOf(FileLogger::class, $logger);
29    }
30}