PHP设计模式 PHP 工厂方法模式

2024-02-26 开发教程 PHP设计模式 匿名 2

目的

相比 简单工厂模式(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);
}
}