本文目录导读:

我来详细介绍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中非常实用的设计模式,特别适合需要动态添加功能的场景,如权限管理、缓存增强、日志记录等。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播