本文目录导读:

我来详细解释PHP中的装饰器模式与动态扩展概念,并提供实用示例。
装饰器模式(Decorator Pattern)
基本概念
装饰器模式允许向现有对象添加新功能,同时不改变其结构。
基础示例
<?php
// 接口定义
interface Coffee
{
public function cost(): float;
public function description(): string;
}
// 基础组件
class SimpleCoffee implements Coffee
{
public function cost(): float
{
return 10.0;
}
public function description(): string
{
return "简单咖啡";
}
}
// 基础装饰器
abstract class CoffeeDecorator implements Coffee
{
protected Coffee $coffee;
public function __construct(Coffee $coffee)
{
$this->coffee = $coffee;
}
abstract public function cost(): float;
abstract public function description(): string;
}
// 具体装饰器 - 牛奶
class MilkDecorator extends CoffeeDecorator
{
public function cost(): float
{
return $this->coffee->cost() + 2.5;
}
public function description(): string
{
return $this->coffee->description() . ",加牛奶";
}
}
// 具体装饰器 - 糖
class SugarDecorator extends CoffeeDecorator
{
public function cost(): float
{
return $this->coffee->cost() + 0.5;
}
public function description(): string
{
return $this->coffee->description() . ",加糖";
}
}
// 具体装饰器 - 奶油
class CreamDecorator extends CoffeeDecorator
{
public function cost(): float
{
return $this->coffee->cost() + 3.0;
}
public function description(): string
{
return $this->coffee->description() . ",加奶油";
}
}
// 使用示例
$coffee = new SimpleCoffee();
echo $coffee->description() . ":¥" . $coffee->cost() . "\n";
$coffeeWithMilk = new MilkDecorator($coffee);
echo $coffeeWithMilk->description() . ":¥" . $coffeeWithMilk->cost() . "\n";
$coffeeWithMilkAndSugar = new SugarDecorator($coffeeWithMilk);
echo $coffeeWithMilkAndSugar->description() . ":¥" . $coffeeWithMilkAndSugar->cost() . "\n";
$fullCoffee = new CreamDecorator($coffeeWithMilkAndSugar);
echo $fullCoffee->description() . ":¥" . $fullCoffee->cost() . "\n";
动态扩展实现
方法1:使用__call魔术方法
<?php
class DynamicObject
{
private array $properties = [];
private array $methods = [];
// 动态设置属性
public function __set(string $name, $value): void
{
$this->properties[$name] = $value;
}
// 动态获取属性
public function __get(string $name)
{
return $this->properties[$name] ?? null;
}
// 动态调用方法
public function __call(string $name, array $arguments)
{
if (isset($this->methods[$name])) {
return call_user_func_array($this->methods[$name], $arguments);
}
throw new \RuntimeException("方法 {$name} 不存在");
}
// 动态添加方法
public function addMethod(string $name, callable $callback): void
{
$this->methods[$name] = $callback;
}
// 检查方法是否存在
public function hasMethod(string $name): bool
{
return isset($this->methods[$name]);
}
}
// 使用示例
$obj = new DynamicObject();
$obj->name = "动态对象";
echo $obj->name . "\n"; // 输出:动态对象
// 动态添加方法
$obj->addMethod('greet', function(string $name) {
return "Hello, {$name}!";
});
$obj->addMethod('calculate', function(float $a, float $b) {
return $a + $b;
});
echo $obj->greet("张三") . "\n"; // 输出:Hello, 张三!
echo $obj->calculate(10, 20) . "\n"; // 输出:30
方法2:使用匿名类(PHP 7+)
<?php
// 基础接口
interface Logger
{
public function log(string $message): void;
}
// 基础实现
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);
}
}
// 使用匿名类动态扩展
function createEnhancedLogger(Logger $baseLogger): Logger
{
return new class($baseLogger) implements Logger {
private Logger $logger;
private array $processedMessages = [];
public function __construct(Logger $logger)
{
$this->logger = $logger;
}
public function log(string $message): void
{
// 添加时间戳
$enhancedMessage = "[" . date('Y-m-d H:i:s') . "] " . $message;
// 记录处理过的消息
$this->processedMessages[] = $enhancedMessage;
// 调用原始logger
$this->logger->log($enhancedMessage);
}
public function getStatistics(): array
{
return [
'total_messages' => count($this->processedMessages),
'messages' => $this->processedMessages
];
}
};
}
// 使用示例
$fileLogger = new FileLogger('/tmp/test.log');
$enhancedLogger = createEnhancedLogger($fileLogger);
$enhancedLogger->log("用户登录");
$enhancedLogger->log("用户退出");
// 获取统计信息
$result = $enhancedLogger->getStatistics();
print_r($result);
方法3:使用Traits实现动态扩展
<?php
// 定义可复用的模块
trait Timestampable
{
private ?\DateTime $createdAt = null;
private ?\DateTime $updatedAt = null;
public function getCreatedAt(): ?\DateTime
{
return $this->createdAt;
}
public function getUpdatedAt(): ?\DateTime
{
return $this->updatedAt;
}
public function markAsCreated(): void
{
$this->createdAt = new \DateTime();
$this->updatedAt = new \DateTime();
}
public function markAsUpdated(): void
{
$this->updatedAt = new \DateTime();
}
}
trait Loggable
{
private array $logs = [];
public function logAction(string $action): void
{
$this->logs[] = [
'action' => $action,
'timestamp' => new \DateTime(),
'user' => $_SERVER['USER'] ?? 'system'
];
}
public function getLogs(): array
{
return $this->logs;
}
}
trait Validateable
{
private array $errors = [];
public function validate(array $data, array $rules): bool
{
$this->errors = [];
foreach ($rules as $field => $rule) {
if (!isset($data[$field]) && strpos($rule, 'required') !== false) {
$this->errors[$field] = "{$field} 是必填字段";
} elseif (isset($data[$field])) {
$this->validateField($field, $data[$field], $rule);
}
}
return empty($this->errors);
}
private function validateField(string $field, $value, string $rule): void
{
// 简化验证逻辑
if (strpos($rule, 'email') !== false && !filter_var($value, FILTER_VALIDATE_EMAIL)) {
$this->errors[$field] = "{$field} 必须是有效的邮箱地址";
}
if (strpos($rule, 'min:') !== false) {
preg_match('/min:(\d+)/', $rule, $matches);
if (!empty($matches) && strlen($value) < (int)$matches[1]) {
$this->errors[$field] = "{$field} 长度不能少于 {$matches[1]} 个字符";
}
}
}
public function getErrors(): array
{
return $this->errors;
}
}
// 使用Traits动态扩展类
class User
{
use Timestampable, Loggable, Validateable;
private string $username;
private string $email;
public function __construct(string $username, string $email)
{
$this->username = $username;
$this->email = $email;
$this->markAsCreated();
}
public function updateEmail(string $email): void
{
$this->email = $email;
$this->markAsUpdated();
$this->logAction('update_email');
}
public function getUsername(): string
{
return $this->username;
}
}
// 使用示例
$user = new User("张三", "zhangsan@example.com");
// 使用Trait提供的方法
echo "创建时间: " . $user->getCreatedAt()->format('Y-m-d H:i:s') . "\n";
$user->updateEmail("newemail@example.com");
echo "更新时间: " . $user->getUpdatedAt()->format('Y-m-d H:i:s') . "\n";
// 查看日志
print_r($user->getLogs());
// 验证数据
$data = ['username' => '李四', 'email' => 'invalid-email'];
$rules = ['username' => 'required|min:2', 'email' => 'required|email'];
if (!$user->validate($data, $rules)) {
print_r($user->getErrors());
}
结合装饰器和动态扩展
<?php
// 高级数据处理器示例
interface DataProcessor
{
public function process(array $data): array;
}
// 基础处理器
class BaseProcessor implements DataProcessor
{
public function process(array $data): array
{
return $data;
}
}
// 装饰器工厂 - 动态创建装饰器
class ProcessorDecoratorFactory
{
public static function create(string $type, DataProcessor $processor): DataProcessor
{
switch ($type) {
case 'filter':
return new class($processor) implements DataProcessor {
private DataProcessor $processor;
public function __construct(DataProcessor $processor)
{
$this->processor = $processor;
}
public function process(array $data): array
{
$data = $this->processor->process($data);
return array_filter($data, fn($item) => !empty($item));
}
};
case 'transform':
return new class($processor) implements DataProcessor {
private DataProcessor $processor;
public function __construct(DataProcessor $processor)
{
$this->processor = $processor;
}
public function process(array $data): array
{
$data = $this->processor->process($data);
return array_map(fn($item) => strtoupper((string)$item), $data);
}
};
case 'validate':
return new class($processor) implements DataProcessor {
private DataProcessor $processor;
public function __construct(DataProcessor $processor)
{
$this->processor = $processor;
}
public function process(array $data): array
{
$data = $this->processor->process($data);
return array_filter($data, fn($item) => is_string($item) && strlen($item) > 0);
}
};
default:
throw new \InvalidArgumentException("未知处理器类型: {$type}");
}
}
}
// 使用示例
$processor = new BaseProcessor();
// 动态添加处理层
$processor = ProcessorDecoratorFactory::create('filter', $processor);
$processor = ProcessorDecoratorFactory::create('validate', $processor);
$processor = ProcessorDecoratorFactory::create('transform', $processor);
$data = ['', 'hello', 'world', null, 'PHP', ' '];
$result = $processor->process($data);
print_r($result);
// 输出: [2] => WORLD, [3] => PHP
性能优化建议
<?php
// 1. 缓存装饰器实例
class DecoratorCache
{
private static array $cache = [];
public static function get(DataProcessor $processor, string $decorator): ?DataProcessor
{
$key = spl_object_id($processor) . '_' . $decorator;
return self::$cache[$key] ?? null;
}
public static function set(DataProcessor $processor, string $decorator, DataProcessor $decorated): void
{
$key = spl_object_id($processor) . '_' . $decorator;
self::$cache[$key] = $decorated;
}
}
// 2. 延迟初始化
class LazyDecorator
{
private ?DataProcessor $processor = null;
private array $decorators = [];
public function addDecorator(string $decorator): void
{
$this->decorators[] = $decorator;
}
public function getProcessor(): DataProcessor
{
if ($this->processor === null) {
$this->processor = new BaseProcessor();
foreach ($this->decorators as $decorator) {
$this->processor = ProcessorDecoratorFactory::create($decorator, $this->processor);
}
}
return $this->processor;
}
}
实际应用场景
- 日志系统:动态添加日志级别、格式化、输出方式
- 缓存系统:添加多级缓存、压缩、序列化
- API中间件:认证、限流、日志记录
- 数据验证:链式验证规则
- ORM系统:动态添加查询条件、结果处理
- 事件系统:动态注册和移除事件处理器
装饰器模式配合动态扩展技术,可以让PHP项目具有极高的灵活性和可扩展性,特别适合需要频繁变更业务逻辑的应用场景。