1.3. Factory Method

1.3.1. Rôle

L’avantage de FactoryMethod sur SimpleFactory est que le factory peut être dérivée afin de mettre oeuvres différentes façons de créer un objet.

Pour les cas simples, cette classe abstraite peut être une simple interface.

Ce modèle est un « vrai » patron de conception car il applique le principe d’inversion des dépendances (Dependency Inversion principle) alias « D » dans SOLID (voir principes SOLID).

Cela signifie que FactoryMethod dépend d’abstractions et non de classes concrètes. C’est son principal avantage par rapport à SimpleFactory ou StaticFactory.

1.3.2. Diagramme UML

Alt FactoryMethod UML Diagram

1.3.3. Code

Vous pouvez également trouver ce code sur 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. Test

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}