PHP装饰器模式动态扩展

wen PHP项目 1

本文目录导读:

PHP装饰器模式动态扩展

  1. 装饰器模式概念
  2. 基础实现
  3. 使用示例
  4. 更实用的示例:权限系统
  5. 高级特性:动态添加方法
  6. 优缺点
  7. 实际应用场景

我来详细介绍PHP装饰器模式的实现和用法。

装饰器模式概念

装饰器模式允许在不修改现有类的情况下,动态地给对象添加新的功能,它通过包装现有对象来扩展功能。

基础实现

基础组件接口和实现

<?php
// 饮料接口
interface Beverage {
    public function getDescription(): string;
    public function getCost(): float;
}
// 具体组件:咖啡
class Coffee implements Beverage {
    protected $description = '普通咖啡';
    protected $cost = 10.0;
    public function getDescription(): string {
        return $this->description;
    }
    public function getCost(): float {
        return $this->cost;
    }
}
// 具体组件:茶
class Tea implements Beverage {
    protected $description = '原味茶';
    protected $cost = 8.0;
    public function getDescription(): string {
        return $this->description;
    }
    public function getCost(): float {
        return $this->cost;
    }
}

装饰器基类

<?php
// 抽象装饰器
abstract class BeverageDecorator implements Beverage {
    protected $beverage;
    public function __construct(Beverage $beverage) {
        $this->beverage = $beverage;
    }
}

具体装饰器

<?php
// 加牛奶装饰器
class MilkDecorator extends BeverageDecorator {
    public function getDescription(): string {
        return $this->beverage->getDescription() . ' + 牛奶';
    }
    public function getCost(): float {
        return $this->beverage->getCost() + 3.0;
    }
}
// 加糖装饰器
class SugarDecorator extends BeverageDecorator {
    public function getDescription(): string {
        return $this->beverage->getDescription() . ' + 糖';
    }
    public function getCost(): float {
        return $this->beverage->getCost() + 1.5;
    }
}
// 加奶油装饰器
class WhipDecorator extends BeverageDecorator {
    public function getDescription(): string {
        return $this->beverage->getDescription() . ' + 奶油';
    }
    public function getCost(): float {
        return $this->beverage->getCost() + 4.0;
    }
}
// 加珍珠装饰器
class BubbleDecorator extends BeverageDecorator {
    public function getDescription(): string {
        return $this->beverage->getDescription() . ' + 珍珠';
    }
    public function getCost(): float {
        return $this->beverage->getCost() + 2.5;
    }
}

使用示例

基础使用

<?php
// 创建一个基础咖啡
$coffee = new Coffee();
echo $coffee->getDescription() . ":¥" . $coffee->getCost() . "\n";
// 输出:普通咖啡:¥10
// 给咖啡加牛奶
$coffeeWithMilk = new MilkDecorator($coffee);
echo $coffeeWithMilk->getDescription() . ":¥" . $coffeeWithMilk->getCost() . "\n";
// 输出:普通咖啡 + 牛奶:¥13
// 继续加糖
$coffeeWithMilkAndSugar = new SugarDecorator($coffeeWithMilk);
echo $coffeeWithMilkAndSugar->getDescription() . ":¥" . $coffeeWithMilkAndSugar->getCost() . "\n";
// 输出:普通咖啡 + 牛奶 + 糖:¥14.5

链式使用

<?php
// 使用链式调用创建复杂组合
$bubbleTea = new BubbleDecorator(
    new SugarDecorator(
        new MilkDecorator(
            new Tea()
        )
    )
);
echo $bubbleTea->getDescription() . ":¥" . $bubbleTea->getCost() . "\n";
// 输出:原味茶 + 牛奶 + 糖 + 珍珠:¥15

更实用的示例:权限系统

<?php
// 权限组件接口
interface Permission {
    public function check(string $action): bool;
    public function getPermissions(): array;
}
// 基础权限
class BasePermission implements Permission {
    protected array $permissions = ['view'];
    public function check(string $action): bool {
        return in_array($action, $this->permissions);
    }
    public function getPermissions(): array {
        return $this->permissions;
    }
}
// 权限装饰器基类
abstract class PermissionDecorator implements Permission {
    protected Permission $permission;
    public function __construct(Permission $permission) {
        $this->permission = $permission;
    }
    public function check(string $action): bool {
        return $this->permission->check($action);
    }
    public function getPermissions(): array {
        return $this->permission->getPermissions();
    }
}
// 添加编辑权限
class EditPermissionDecorator extends PermissionDecorator {
    public function check(string $action): bool {
        if ($action === 'edit') {
            return true;
        }
        return parent::check($action);
    }
    public function getPermissions(): array {
        $permissions = parent::getPermissions();
        $permissions[] = 'edit';
        return array_unique($permissions);
    }
}
// 添加删除权限
class DeletePermissionDecorator extends PermissionDecorator {
    public function check(string $action): bool {
        if ($action === 'delete') {
            return true;
        }
        return parent::check($action);
    }
    public function getPermissions(): array {
        $permissions = parent::getPermissions();
        $permissions[] = 'delete';
        return array_unique($permissions);
    }
}
// 添加管理权限
class AdminPermissionDecorator extends PermissionDecorator {
    public function check(string $action): bool {
        // 管理员拥有所有权限
        return true;
    }
    public function getPermissions(): array {
        return ['view', 'edit', 'delete', 'manage', 'settings'];
    }
}
// 使用示例
$userPermission = new BasePermission();
$editorPermission = new EditPermissionDecorator($userPermission);
$adminPermission = new AdminPermissionDecorator($userPermission);
echo $userPermission->check('edit') ? '可以编辑' : '不能编辑'; // 不能编辑
echo $editorPermission->check('edit') ? '可以编辑' : '不能编辑'; // 可以编辑
echo $adminPermission->check('delete') ? '可以删除' : '不能删除'; // 可以删除

高级特性:动态添加方法

<?php
// 使用魔术方法实现动态扩展
class DynamicDecorator {
    protected $wrapped;
    protected $extras = [];
    public function __construct($wrapped) {
        $this->wrapped = $wrapped;
    }
    public function addExtra(string $name, callable $callable) {
        $this->extras[$name] = $callable;
        return $this;
    }
    public function __call($method, $arguments) {
        // 先尝试调用包装对象的方法
        if (method_exists($this->wrapped, $method)) {
            return $this->wrapped->$method(...$arguments);
        }
        // 检查是否有扩展方法
        if (isset($this->extras[$method])) {
            return call_user_func_array($this->extras[$method], $arguments);
        }
        throw new BadMethodCallException("方法 $method 不存在");
    }
    public function __get($name) {
        if (property_exists($this->wrapped, $name)) {
            return $this->wrapped->$name;
        }
        return null;
    }
    public function __set($name, $value) {
        $this->wrapped->$name = $value;
    }
}
// 使用示例
class Order {
    public $total = 100;
    public function getTotal() {
        return $this->total;
    }
}
$order = new Order();
$orderDecorator = (new DynamicDecorator($order))
    ->addExtra('withDiscount', function($percent) {
        return $this->getTotal() * (1 - $percent/100);
    })
    ->addExtra('withTax', function() {
        return $this->getTotal() * 1.1;
    });
echo $orderDecorator->getTotal(); // 调用原始方法
echo $orderDecorator->withDiscount(20); // 调用扩展方法

优缺点

优点

  • 动态添加功能,灵活性高
  • 遵循开闭原则,无需修改现有代码
  • 可以组合多个装饰器,实现丰富功能
  • 避免创建过多子类

缺点

  • 会产生大量小类
  • 增加系统复杂度
  • 调试困难(多层嵌套)
  • 性能有一定影响

实际应用场景

<?php
// 缓存装饰器示例
interface CacheInterface {
    public function get(string $key);
    public function set(string $key, $value, int $ttl = 3600);
}
class RedisCache implements CacheInterface {
    public function get(string $key) {
        // Redis 获取逻辑
        return "data from redis";
    }
    public function set(string $key, $value, int $ttl = 3600) {
        // Redis 设置逻辑
        return true;
    }
}
// 日志装饰器
class LoggingCacheDecorator implements CacheInterface {
    protected $cache;
    protected $logFile;
    public function __construct(CacheInterface $cache, string $logFile) {
        $this->cache = $cache;
        $this->logFile = $logFile;
    }
    public function get(string $key) {
        $start = microtime(true);
        $result = $this->cache->get($key);
        $this->log("GET $key", microtime(true) - $start);
        return $result;
    }
    public function set(string $key, $value, int $ttl = 3600) {
        $result = $this->cache->set($key, $value, $ttl);
        $this->log("SET $key");
        return $result;
    }
    protected function log(string $message, float $time = 0) {
        $log = sprintf("[%s] %s (%.4fs)\n", date('Y-m-d H:i:s'), $message, $time);
        file_put_contents($this->logFile, $log, FILE_APPEND);
    }
}
// 压缩装饰器
class CompressCacheDecorator implements CacheInterface {
    protected $cache;
    public function __construct(CacheInterface $cache) {
        $this->cache = $cache;
    }
    public function get(string $key) {
        $data = $this->cache->get($key);
        return $data ? gzuncompress($data) : null;
    }
    public function set(string $key, $value, int $ttl = 3600) {
        $compressed = gzcompress($value);
        return $this->cache->set($key, $compressed, $ttl);
    }
}
// 使用
$cache = new RedisCache();
$cache = new LoggingCacheDecorator($cache, '/tmp/cache.log');
$cache = new CompressCacheDecorator($cache);
// $cache 同时具有日志和压缩功能

装饰器模式是PHP中非常实用的设计模式,特别适合需要动态添加功能的场景,如权限管理、缓存增强、日志记录等。

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