1.3. Factory Method

1.3.1. Amaç

Fabrika Yöntemi’nin güzel tarafı Simple Factory aksine, kendisini alt neslerle genişleterek (subclassing), bu yolla farklı biçimlerde nesne oluşturabilmeye olanak sağlamasıdır.

For simple cases, this abstract class could be just an interface.

Bu desen “gerçek” bir Tasarım Deseni’dir, çünkü S.O.L.I.D ilkelerinden biri olan “D” yani “Dependency Inversion Principle (Bağımlılık Tersinme İlkesi)” bölümünün sorumluluğunu yerine getirir.

Bu, Factory Method sınıfının somut sınıflara değil soyutlamalara (abstraction) dayandığı anlamına gelir. İşte işin püf noktası da, Simple Factory veya Static Factory ile karşılaştırıldığında budur.

1.3.2. UML Diyagramı

Alt FactoryMethod UML Diagram

1.3.3. Kod

Bu kodu Github üzerinde de bulabilirsiniz.

Logger.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?php

declare(strict_types=1);

namespace DesignPatterns\Creational\FactoryMethod;

interface Logger
{
    public function log(string $message);
}

StdoutLogger.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php

declare(strict_types=1);

namespace DesignPatterns\Creational\FactoryMethod;

class StdoutLogger implements Logger
{
    public function log(string $message)
    {
        echo $message;
    }
}

FileLogger.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php

declare(strict_types=1);

namespace DesignPatterns\Creational\FactoryMethod;

class FileLogger implements Logger
{
    public function __construct(private string $filePath)
    {
    }

    public function log(string $message)
    {
        file_put_contents($this->filePath, $message . PHP_EOL, FILE_APPEND);
    }
}

LoggerFactory.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?php

declare(strict_types=1);

namespace DesignPatterns\Creational\FactoryMethod;

interface LoggerFactory
{
    public function createLogger(): Logger;
}

StdoutLoggerFactory.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?php

declare(strict_types=1);

namespace DesignPatterns\Creational\FactoryMethod;

class StdoutLoggerFactory implements LoggerFactory
{
    public function createLogger(): Logger
    {
        return new StdoutLogger();
    }
}

FileLoggerFactory.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<?php

declare(strict_types=1);

namespace DesignPatterns\Creational\FactoryMethod;

class FileLoggerFactory implements LoggerFactory
{
    public function __construct(private string $filePath)
    {
    }

    public function createLogger(): Logger
    {
        return new FileLogger($this->filePath);
    }
}

1.3.4. Test

Tests/FactoryMethodTest.php

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php

declare(strict_types=1);

namespace DesignPatterns\Creational\FactoryMethod\Tests;

use DesignPatterns\Creational\FactoryMethod\FileLogger;
use DesignPatterns\Creational\FactoryMethod\FileLoggerFactory;
use DesignPatterns\Creational\FactoryMethod\StdoutLogger;
use DesignPatterns\Creational\FactoryMethod\StdoutLoggerFactory;
use PHPUnit\Framework\TestCase;

class FactoryMethodTest extends TestCase
{
    public function testCanCreateStdoutLogging()
    {
        $loggerFactory = new StdoutLoggerFactory();
        $logger = $loggerFactory->createLogger();

        $this->assertInstanceOf(StdoutLogger::class, $logger);
    }

    public function testCanCreateFileLogging()
    {
        $loggerFactory = new FileLoggerFactory(sys_get_temp_dir());
        $logger = $loggerFactory->createLogger();

        $this->assertInstanceOf(FileLogger::class, $logger);
    }
}