相比 簡(jiǎn)單工廠模式(SimpleFactory)而言,工廠方法模式(Factory Method)可以通過(guò)延伸出子類(lèi),實(shí)現(xiàn)用不同的方法創(chuàng)建對(duì)象。
對(duì)于比較簡(jiǎn)單的情況,這個(gè)抽象類(lèi)可能只是一個(gè)接口。
這是一個(gè) “真正” 的設(shè)計(jì)模式,因?yàn)樗裱恕币蕾?lài)反轉(zhuǎn)原則(Dependency Inversion Principle)” 。也就是 SOLID 原則中的”D”。
這意味著工廠方法實(shí)現(xiàn)的類(lèi)依賴(lài)于類(lèi)的抽象,而不是具體的類(lèi)。這也是 工廠方法模式 與 簡(jiǎ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); } }
更多建議: