Purpose
The good point over the SimpleFactory is you can subclass it to implement different ways to create objects.
For simple cases, this abstract class could be just an interface.
This pattern is a "real" Design Pattern because it achieves the Dependency Inversion principle. The "D" in SOLID principles.
It means the FactoryMethod class depends on abstractions, not concrete classes. This is the real trick compared to SimpleFactory or StaticFactory.
Logger.php
<?php namespace DesignPatterns\Creational\FactoryMethod; interface Logger { public function log(string $message); }
StdoutLogger.php
<?php namespace DesignPatterns\Creational\FactoryMethod; class StdoutLogger implements Logger { public function log(string $message) { echo $message; } }
FileLogger.php
<?php namespace DesignPatterns\Creational\FactoryMethod; class FileLogger implements Logger { /** * @var string */ 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
<?php namespace DesignPatterns\Creational\FactoryMethod; interface LoggerFactory { public function createLogger(): Logger; }
StdoutLoggerFactory.php
<?php namespace DesignPatterns\Creational\FactoryMethod; class StdoutLoggerFactory implements LoggerFactory { public function createLogger(): Logger { return new StdoutLogger(); } }
FileLoggerFactory.php
<?php namespace DesignPatterns\Creational\FactoryMethod; class FileLoggerFactory implements LoggerFactory { /** * @var string */ private $filePath; public function __construct(string $filePath) { $this->filePath = $filePath; } public function createLogger(): Logger { return new FileLogger($this->filePath); } }
Tests/FactoryMethodTest.php
<?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); } }
原文:https://www.cnblogs.com/victorchen/p/10826142.html