目的
对比简单工厂模式的优点是,您可以将其子类用不同的方法来创建一个对象。
举一个简单的例子,这个抽象类可能只是一个接口。
这种模式是「真正」的设计模式, 因为他实现了 S.O.L.I.D 原则中「D」的 「依赖倒置」。
这意味着工厂方法模式取决于抽象类,而不是具体的类。 这是与简单工厂模式和静态工厂模式相比的优势。
代码
Logger.php
1 2 3 4 5 6
| <?php namespace DesignPatterns\Creational\FactoryMethod; interface Logger { public function log(string $message); }
|
StdoutLogger.php
1 2 3 4 5 6 7 8 9
| <?php 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 namespace DesignPatterns\Creational\FactoryMethod; class FileLogger implements Logger {
private $filePath; public function __construct(string $filePath) { $this->filePath = $filePath; } public function log(string $message) { file_put_contents($this->filePath, $message . PHP_EOL, FILE_APPEND); } }
|
LoggerFactory.php
1 2 3 4 5 6
| <?php namespace DesignPatterns\Creational\FactoryMethod; interface LoggerFactory { public function createLogger(): Logger; }
|
StdoutLoggerFactory.php
1 2 3 4 5 6 7 8 9
| <?php 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 namespace DesignPatterns\Creational\FactoryMethod; class FileLoggerFactory implements LoggerFactory {
private $filePath; public function __construct(string $filePath) { $this->filePath = $filePath; } public function createLogger(): Logger { return new FileLogger($this->filePath); } }
|
测试
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
| <?php 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); } }
|