PHP 工厂方法模式
目的
相比 简单工厂模式(SimpleFactory)而言,工厂方法模式(Factory Method)可以通过延伸出子类,实现用不同的方法创建对象。
对于比较简单的情况,这个抽象类可能只是一个接口。
这是一个 “真正” 的设计模式,因为它遵循了”依赖反转原则(Dependency Inversion Principle)” 。也就是 SOLID 原则中的”D”。
这意味着工厂方法实现的类依赖于类的抽象,而不是具体的类。这也是 工厂方法模式 与 简单工厂模式 和 静态工厂模式 之间最重要的区别。
1.3.2. UML 图
1.3.3. 代码
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); } }