设计模式整理--装饰器模式

前言


继续上次的工厂模式, 接下来要整理的是装饰器模式, 废话不多说.

遇到的问题


当我们有一个远古的类, 或者复杂的类, 又或者我们在这个类上需要作出一点修改, 这个时候如果 继承不太合适, 当然不合适的原因可能很多, 比如 这个类继承出来的子类没有语义环境. 又或者继承子类容易脏代码. 这个时候我们需要一个简单的办法能够修改原来的类, 但又不能违背开闭的原则.

代码示例


如果需要装饰的是类的抽象, 需要多实现一个接口.

// 类抽象
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();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章