前言
继续上次的工厂模式, 接下来要整理的是装饰器模式, 废话不多说.
遇到的问题
当我们有一个远古的类, 或者复杂的类, 又或者我们在这个类上需要作出一点修改, 这个时候如果 继承不太合适, 当然不合适的原因可能很多, 比如 这个类继承出来的子类没有语义环境. 又或者继承子类容易脏代码. 这个时候我们需要一个简单的办法能够修改原来的类, 但又不能违背开闭的原则.
代码示例
如果需要装饰的是类的抽象, 需要多实现一个接口.
// 类抽象
interface Phone
{
public function call(): void;
}
// 源类
class Iphone impletements Phone
{
public function call(): void
{
echo "call";
}
}
// 装饰类
class IphoneDecorator impletements Phone
{
private Phone $phone;
public function __contruct(Phone $phone)
{
$this->phone = $phone;
}
public function call(): void
{
// call 需要做的新事情 伪代码
echo "before call";
$this->phone->call();
echo "end call";
}
}
// 使用装饰器
(new IphoneDecorator(new Iphone()))->call();
如果装饰器实现多态, 那么装饰器本身也需要抽象, 如下:
// 类抽象
interface Phone
{
public function call(): void;
}
// 源类
class Iphone impletements Phone
{
public function call(): void
{
echo "call";
}
}
// 装饰类抽象
interface IphoneDecorator extends Phone
{
}
// 装饰类
class IphoneCallUserDecorator impletements IphoneDecorator
{
private Phone $phone;
public function __contruct(Phone $phone)
{
$this->phone = $phone;
}
public function call(): void
{
// call 需要做的新事情 伪代码
echo "call user";
$this->phone->call();
}
}
// 装饰类
class IphoneCallAdminDecorator impletements IphoneDecorator
{
private Phone $phone;
public function __contruct(Phone $phone)
{
$this->phone = $phone;
}
public function call(): void
{
// call 需要做的新事情 伪代码
echo "call admin";
$this->phone->call();
}
}
// 此时可以动态选择装饰器
(new IphoneCallAdminDecorator(new Iphone()))->call();
(new IphoneCallUserDecorator(new Iphone()))->call();
如果需要装饰的是类本身, 并且不需要实现多态装饰可以简化, 如下:
// 源类
class Iphone
{
public function call(): void
{
echo "call";
}
}
// 装饰类
class IphoneDecorator
{
private Iphone $phone;
public function __contruct(Iphone $phone)
{
$this->phone = $phone;
}
public function call(): void
{
// call 需要做的新事情 伪代码
echo "before call";
$this->phone->call();
echo "end call";
}
}
// 使用装饰器
(new IphoneDecorator(new Iphone()))->call();