相比 簡單工廠模式(SimpleFactory)而言,工廠方法模式(Factory Method)可以通過延伸出子類,實現(xiàn)用不同的方法創(chuàng)建對象。
對于比較簡單的情況,這個抽象類可能只是一個接口。
這是一個 “真正” 的設(shè)計模式,因為它遵循了”依賴反轉(zhuǎn)原則(Dependency Inversion Principle)” 。也就是 SOLID 原則中的”D”。
這意味著工廠方法實現(xiàn)的類依賴于類的抽象,而不是具體的類。這也是 工廠方法模式 與 簡單工廠模式 和 靜態(tài)工廠模式 之間最重要的區(qū)別。
Logger.php
<?php declare(strict_types=1); namespace DesignPatterns\Creational\FactoryMethod; interface Logger{ public function log(string $message); }
StdoutLogger.php
<?php declare(strict_types=1); namespace DesignPatterns\Creational\FactoryMethod; class StdoutLogger implements Logger{ public function log(string $message){ echo $message; } }
FileLogger.php
<?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
<?php declare(strict_types=1); namespace DesignPatterns\Creational\FactoryMethod; interface LoggerFactory{ public function createLogger(): Logger; }
StdoutLoggerFactory.php
<?php declare(strict_types=1); namespace DesignPatterns\Creational\FactoryMethod; class StdoutLoggerFactory implements LoggerFactory { public function createLogger(): Logger { return new StdoutLogger(); } }
FileLoggerFactory.php
<?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); } }
Tests/FactoryMethodTest.php
<?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); } }
更多建議: