本文目录导读:

我会为你详细讲解 PHP 项目中工厂模式与抽象工厂模式的区别、实现方式及应用场景,并配合实际代码示例。
工厂模式(Factory Pattern)
核心概念
工厂模式定义一个创建对象的接口,让子类决定实例化哪一个类,它封装了对象创建的逻辑。
适用场景
- 当需要根据条件动态创建不同类型的对象时
- 当对象创建过程复杂,需要集中管理时
- 当需要解耦客户端代码与具体产品类时
PHP 实现示例
<?php
// 1. 产品接口
interface Logger {
public function log(string $message): void;
}
// 2. 具体产品实现
class FileLogger implements Logger {
private string $filePath;
public function __construct(string $filePath) {
$this->filePath = $filePath;
}
public function log(string $message): void {
file_put_contents($this->filePath, $message . PHP_EOL, FILE_APPEND);
echo "FileLogger: 记录日志到文件 {$this->filePath}\n";
}
}
class DatabaseLogger implements Logger {
private string $connectionString;
public function __construct(string $connectionString) {
$this->connectionString = $connectionString;
}
public function log(string $message): void {
// 模拟数据库日志记录
echo "DatabaseLogger: 记录日志到数据库 {$this->connectionString}\n";
}
}
class CloudLogger implements Logger {
private string $apiKey;
public function __construct(string $apiKey) {
$this->apiKey = $apiKey;
}
public function log(string $message): void {
echo "CloudLogger: 记录日志到云服务\n";
}
}
// 3. 工厂类
class LoggerFactory {
public static function createLogger(string $type, array $config = []): Logger {
switch ($type) {
case 'file':
$filePath = $config['file_path'] ?? '/var/log/app.log';
return new FileLogger($filePath);
case 'database':
$connectionString = $config['connection'] ?? 'mysql://localhost:3306';
return new DatabaseLogger($connectionString);
case 'cloud':
$apiKey = $config['api_key'] ?? 'default-key';
return new CloudLogger($apiKey);
default:
throw new InvalidArgumentException("不支持的日志类型: {$type}");
}
}
}
// 4. 客户端代码
class Application {
private Logger $logger;
public function __construct(string $logType, array $config = []) {
// 客户端不需要知道日志类的具体创建细节
$this->logger = LoggerFactory::createLogger($logType, $config);
}
public function run(): void {
$this->logger->log("应用启动成功");
$this->logger->log("用户登录系统");
}
}
// 使用示例
try {
$app1 = new Application('file', ['file_path' => './logs/app.log']);
$app1->run();
$app2 = new Application('database', ['connection' => 'mysql://user:pass@localhost']);
$app2->run();
$app3 = new Application('cloud', ['api_key' => 'abc123']);
$app3->run();
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "\n";
}
抽象工厂模式(Abstract Factory Pattern)
核心概念
抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类,它是工厂模式的升级版。
适用场景
- 系统需要独立于产品的创建、组合和表示
- 系统需要产品族的概念
- 需要提供产品类库,只想暴露接口而非实现
PHP 实现示例
<?php
// ========== 产品族1: 按钮 ==========
interface Button {
public function render(): string;
public function onClick(): void;
}
class WindowsButton implements Button {
public function render(): string {
return "渲染 Windows 风格的按钮";
}
public function onClick(): void {
echo "Windows 按钮被点击\n";
}
}
class MacButton implements Button {
public function render(): string {
return "渲染 Mac 风格的按钮";
}
public function onClick(): void {
echo "Mac 按钮被点击\n";
}
}
class LinuxButton implements Button {
public function render(): string {
return "渲染 Linux 风格的按钮";
}
public function onClick(): void {
echo "Linux 按钮被点击\n";
}
}
// ========== 产品族2: 文本框 ==========
interface TextBox {
public function render(): string;
public function getText(): string;
}
class WindowsTextBox implements TextBox {
public function render(): string {
return "渲染 Windows 风格的文本框";
}
public function getText(): string {
return "Windows 文本框内容";
}
}
class MacTextBox implements TextBox {
public function render(): string {
return "渲染 Mac 风格的文本框";
}
public function getText(): string {
return "Mac 文本框内容";
}
}
class LinuxTextBox implements TextBox {
public function render(): string {
return "渲染 Linux 风格的文本框";
}
public function getText(): string {
return "Linux 文本框内容";
}
}
// ========== 抽象工厂 ==========
interface GUIFactory {
public function createButton(): Button;
public function createTextBox(): TextBox;
}
// ========== 具体工厂 ==========
class WindowsFactory implements GUIFactory {
public function createButton(): Button {
return new WindowsButton();
}
public function createTextBox(): TextBox {
return new WindowsTextBox();
}
}
class MacFactory implements GUIFactory {
public function createButton(): Button {
return new MacButton();
}
public function createTextBox(): TextBox {
return new MacTextBox();
}
}
class LinuxFactory implements GUIFactory {
public function createButton(): Button {
return new LinuxButton();
}
public function createTextBox(): TextBox {
return new LinuxTextBox();
}
}
// ========== 客户端代码 ==========
class ApplicationUI {
private Button $button;
private TextBox $textBox;
public function __construct(GUIFactory $factory) {
// 客户端只知道使用工厂,不知道具体产品
$this->button = $factory->createButton();
$this->textBox = $factory->createTextBox();
}
public function render(): void {
echo $this->button->render() . "\n";
echo $this->textBox->render() . "\n";
$this->button->onClick();
echo "文本框内容: " . $this->textBox->getText() . "\n";
}
}
// ========== 扩展:工厂选择器 ==========
class UIFactorySelector {
public static function getFactory(string $osType): GUIFactory {
return match ($osType) {
'windows' => new WindowsFactory(),
'mac' => new MacFactory(),
'linux' => new LinuxFactory(),
default => throw new InvalidArgumentException("不支持的 OS: {$osType}")
};
}
}
// ========== 使用示例 ==========
try {
echo "=== Windows UI ===\n";
$windowsApp = new ApplicationUI(new WindowsFactory());
$windowsApp->render();
echo "\n=== Mac UI ===\n";
$macApp = new ApplicationUI(new MacFactory());
$macApp->render();
echo "\n=== Linux UI ===\n";
$linuxApp = new ApplicationUI(new LinuxFactory());
$linuxApp->render();
echo "\n=== 使用工厂选择器 ===\n";
$osType = 'windows';
$app = new ApplicationUI(UIFactorySelector::getFactory($osType));
$app->render();
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "\n";
}
两者的核心区别
| 特性 | 工厂模式 | 抽象工厂模式 |
|---|---|---|
| 创建对象数量 | 创建单一产品 | 创建产品族(多个相关产品) |
| 复杂度 | 较低 | 较高 |
| 扩展维度 | 新增产品类型(纵向) | 新增产品族(横向)或产品种类 |
| 客户端耦合 | 耦合单一产品接口 | 耦合多个产品接口 |
| 典型应用 | 日志系统、数据库连接 | UI组件库、跨平台工具集 |
混合使用示例(工厂模式 + 抽象工厂)
<?php
// 配置系统 - 结合两种模式
interface DatabaseConnection {
public function connect(): void;
public function query(string $sql): array;
}
interface CacheSystem {
public function set(string $key, $value): void;
public function get(string $key);
}
// 具体实现...
// 抽象工厂
interface InfrastructureFactory {
public function createDatabase(): DatabaseConnection;
public function createCache(): CacheSystem;
}
// 工厂方法(用于创建具体的工厂)
class InfrastructureFactoryManager {
public static function getFactory(string $environment): InfrastructureFactory {
return match ($environment) {
'development' => new DevelopmentInfrastructureFactory(),
'production' => new ProductionInfrastructureFactory(),
'testing' => new TestingInfrastructureFactory(),
default => throw new \InvalidArgumentException("Invalid environment")
};
}
}
实际项目建议
-
选择合适的模式:
- 产品种类固定但实现多变 → 工厂模式
- 产品族需要保持一致性 → 抽象工厂模式
-
避免过度设计:不要为简单场景使用复杂模式
-
结合依赖注入容器:现代 PHP 框架(如 Laravel、Symfony)都支持自动依赖注入,可以简化工厂实现
-
考虑扩展性:设计时预留扩展点,但不要过度抽象
工厂模式和抽象工厂模式是创建型设计模式的核心,它们能显著提高代码的可维护性和可扩展性,建议在实际项目中根据需求灵活运用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播