PHP项目装饰器与动态扩展

wen PHP项目 1

本文目录导读:

PHP项目装饰器与动态扩展

  1. 装饰器模式(Decorator Pattern)
  2. 动态扩展实现
  3. 结合装饰器和动态扩展
  4. 性能优化建议
  5. 实际应用场景

我来详细解释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项目具有极高的灵活性和可扩展性,特别适合需要频繁变更业务逻辑的应用场景。

抱歉,评论功能暂时关闭!