php-装饰器模式实现
概述
装饰模式(Decorator Pattern) :动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。其别名也可以称为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。根据翻译的不同,装饰模式也有人称之为“油漆工模式”,它是一种对象结构型模式。
我们这里还是以摩托车制造为例。现在我们需要对踏板摩托车进行自定义配件的装饰以及我们希望对其进行第三方质检操作。那么我们就可以用到装饰器模式
模式结构
以本文实例代码为参考
- MotorcycleProduce-摩托组装抽象类:建立摩托组装标准工艺
- MotocycleProduct-摩托车产品本身
- MotorcycleScooter-踏板摩托车
- MotorDecorator-抽象摩托车装饰器类
- MotorDecoratorA-装饰器A
- MotorDecoratorB-装饰器B
UML图例
代码实例
<?php
namespace Decorator;
interface MotorcycleProduce
{
public function addEngine();
public function addBody();
public function addWhell();
public function getMotor();
}
class MotocycleProduct{
private $motor = [
"engine"=>"",
"body"=>"",
"whell"=>"",
"bodyColor"=>"blue"
];
public function addEngine($engine){
$this->motor["engine"] = $engine;
}
public function addBody($body){
$this->motor["body"] = $body;
}
public function addWhell($whell){
$this->motor["whell"] = $whell;
}
public function getMotor(){
return $this->motor;
}
}
class MotorcycleScooter implements MotorcycleProduce
{
private $motor;
public function __construct()
{
$this->motor = new MotocycleProduct();
}
function addEngine()
{
$this->motor->addEngine("踏板摩托-发动机已装好");
}
function addBody()
{
$this->motor->addBody("踏板摩托-车身已装好");
}
function addWhell()
{
$this->motor->addWhell("踏板摩托-车轮已装好");
}
function getMotor()
{
return $this->motor->getMotor();
}
}
abstract class MotorDecorator implements MotorcycleProduce{
protected $motor_cycle;
public function __construct(MotorcycleProduce $motor_cycle){
$this->motor_cycle = $motor_cycle;
}
}
class MotorDecoratorA extends MotorDecorator{
public function addEngine(){
$this->motor_cycle->addEngine();
}
public function addBody()
{
$this->motor_cycle->addBody();
}
public function addWhell()
{
$this->motor_cycle->addWhell();
}
public function getMotor()
{
$motor = $this->motor_cycle->getMotor();
$motor["other"] = "个性化配件";
return $motor;
}
}
class MotorDecoratorB extends MotorDecorator{
public function checkMoto(){
echo "摩托合规性检测-合规<br>";
}
public function addEngine(){
$this->motor_cycle->addEngine();
}
public function addBody()
{
$this->motor_cycle->addBody();
}
public function addWhell()
{
$this->motor_cycle->addWhell();
}
public function getMotor()
{
$motor = $this->motor_cycle->getMotor();
$this->checkMoto();
return $motor;
}
}
$motorScooter = new MotorcycleScooter();
$motorDecoratorA = new MotorDecoratorA($motorScooter);
$motorDecoratorA->addEngine();
$motorDecoratorA->addBody();
$motorDecoratorA->addWhell();
$motor = $motorDecoratorA->getMotor();
var_dump($motor);
echo "<br>";
$motorDecoratorB = new MotorDecoratorB($motorScooter);
$motorDecoratorB->addEngine();
$motorDecoratorB->addBody();
$motorDecoratorB->addWhell();
$motor = $motorDecoratorB->getMotor();
var_dump($motor);
模式分析
- 使用装饰模式来实现扩展比继承更加灵活,它以对客户透明的方式动态地给一个对象附加更多的责任。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。
- 相比继承,关联关系的主要优势在于不会破坏原有产品类的封装性,继承是一种耦合度将大的静态关系,扩展起来相对麻烦。不便于后期的维护。由于关联关系使系统具备较好的松耦合性。使得系统更加容易维护。
优缺点
装饰模式的优点:
- 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
- 可以通过一种动态的方式来扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。
- 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
- 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”
装饰模式的缺点:
- 装饰器模式下会产生很多小对象,这些对象的区别在于他们之间相互连接的方式有所不同。随着装饰类和小对象的增多将会增加系统的复杂度,从而导致了系统在学习和理解起来会相对困难。
- 由于类的灵活的特性,也同时意味着装饰模式更容易出错,且不容易排错,对于多次装饰的对象,在排错时相对繁琐。
适用环境
在以下情况下可以使用装饰模式:
- 需要动态的调整单个对象的职责。
- 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。不能采用继承的情况主要有两类:第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;第二类是因为类定义不能继承(如final类).
获取更多学习资源请关注微信公众号:yuantanphp
|