设计模式-装饰模式

案例:小菜出门约会穿衣

第一版代码:

class Person {
  private $name;
  public function __construct($name)
  {
    $this->name = $name;
  }

  public function WearTShirts()
  {
    echo '大T恤 ';
  }

  public function WearBigTrouser()
  {
    echo '跨裤 ';
  }

  public function WearSneakers()
  {
    echo '破球鞋 ';
  }

  public function WearSuit()
  {
    echo '西装 ';
  }

  public function WearTie()
  {
    echo '领带 ';
  }

  public function WearLeatherShoes()
  {
    echo '皮鞋 ';
  }

  public function Show()
  {
    echo "装扮的{$this->name}";
  }
}

//客户端代码
$Person = new Person('小菜');

echo "第一种装扮:";
$Person->WearTShirts();
$Person->WearBigTrouser();
$Person->WearSneakers();
$Person->Show();

echo "\n第二种装扮:";
$Person->WearSuit();
$Person->WearTie();
$Person->WearLeatherShoes();
$Person->Show();

功能是实现了,如果要加入“超人”的装扮,就得修改Person类,这样就违反了开放-封闭原则了。

第二版代码:
把这些服饰都写成子类

class Person {
  private $name;
  public function __construct($name)
  {
    $this->name = $name;
  }

  public function Show()
  {
    echo "装扮的{$this->name}";
  }
}

//服饰抽象类
abstract class Finery {
  public abstract function Show();
}
//大T恤子类
class TShirts extends Finery {

  public function Show()
  {
    // TODO: Implement Show() method.
    echo '大T恤 ';
  }
}
//跨裤子类
class BigTrouser extends Finery {

  public function Show()
  {
    // TODO: Implement Show() method.
    echo '跨裤 ';
  }
}
//破球鞋子类
class Sneakers extends Finery {

  public function Show()
  {
    // TODO: Implement Show() method.
    echo '破球鞋 ';
  }
}
//西装子类
class Suit extends Finery {

  public function Show()
  {
    // TODO: Implement Show() method.
    echo '西装 ';
  }
}
//领带子类
class Tie extends Finery {

  public function Show()
  {
    // TODO: Implement Show() method.
    echo '领带 ';
  }
}
//皮鞋子类
class LeatherShoes extends Finery {

  public function Show()
  {
    // TODO: Implement Show() method.
    echo '皮鞋 ';
  }
}

//客户端代码
$Person = new Person('小菜');

echo "第一种装扮:";
$dtx = new TShirts();
$kk = new BigTrouser();
$pqx = new Sneakers();
$dtx->Show();
$kk->Show();
$pqx->Show();
$Person->Show();

echo "\n第二种装扮:";
$xz = new Suit();
$ld = new Tie();
$px = new LeatherShoes();
$xz->Show();
$ld->Show();
$px->Show();
$Person->Show();

第三版代码:

角色:

  • 组件对象的接口: 定义给这些对象动态添加职责的方法
  • 待装饰对象: 被扩展的对象。
  • 所有装饰器的父类: 实现 组件对象的接口,并持有一个Component对象(该对象其实就是被装饰的对象),定义添加职责的方法,使其调用Component对象的添加职责方法。
  • 具体的装饰器类: 实现具体要向被装饰对象添加的功能。用来装饰具体的组件对象或者另外一个具体的装饰器对象
//组件对象接口
interface IComponent {
    public function Display();
}

//待装饰对象
class Person implements IComponent {

    private $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function Display()
    {
        // TODO: Implement Display() method.
        echo "装饰的: {$this->name} \n";
    }
}

//所有装饰器父类
class Clothes implements IComponent {

    protected $component;

    public function Decorate(IComponent $component)
    {
        $this->component = $component;
    }

    public function Display()
    {
        // TODO: Implement Display() method.
        if(!empty($this->component))
        {
            $this->component->Display();
        }
    }
}
//------------------------------具体装饰器----------------
//大T恤子类
class TShirts extends Clothes {
    public function Display()
    {
        echo "大T恤 ";
        parent::Display(); // TODO: Change the autogenerated stub
    }
}
//跨裤子类
class BigTrouser extends Clothes {
    public function Display()
    {
        echo "跨裤 ";
        parent::Display(); // TODO: Change the autogenerated stub
    }
}
//破球鞋子类
class Sneakers extends Clothes {
    public function Display()
    {
        echo "破球鞋 ";
        parent::Display(); // TODO: Change the autogenerated stub
    }
}
//西装子类
class Suit extends Clothes {
    public function Display()
    {
        echo "西装 ";
        parent::Display(); // TODO: Change the autogenerated stub
    }
}
//领带子类
class Tie extends Clothes {
    public function Display()
    {
        echo "领带 ";
        parent::Display(); // TODO: Change the autogenerated stub
    }
}
//皮鞋子类
class LeatherShoes extends Clothes {
    public function Display()
    {
        echo "皮鞋 ";
        parent::Display(); // TODO: Change the autogenerated stub
    }
}

//客户端代码
$Person = new Person('小菜');

echo "第一种装扮:";
$dtx = new TShirts();
$kk = new BigTrouser();
$pqx = new Sneakers();
$pqx->Decorate($Person);
$kk->Decorate($pqx);
$dtx->Decorate($kk);
$dtx->Display();

echo "第二种装扮:";
$xz = new Suit();
$ld = new Tie();
$px = new LeatherShoes();
$px->Decorate($Person);
$ld->Decorate($px);
$xz->Decorate($ld);
$xz->Display();

对客户端调用解释:
$Person = new Person('小菜');
创建一个待装饰对象 ,也是一个Component对象

$dtx = new TShirts();
$kk = new BigTrouser();
$pqx = new Sneakers();

创建了3个具体的装饰器类,也就是3个Component对象

$pqx->Decorate($Person);

把待装饰对象放进具体装饰器Sneakers中,$pqx的component为$Person对象

$kk->Decorate($pqx);

$pqx对象放进具体装饰器BigTrouser中,$kk的component为$pqx对象

$dtx->Decorate($kk);

$kk对象放进具体装饰器TShirts中,$dtx的component为$kk对象

$dtx->Display();

$dtx调用自身的Display()方法,输出“大T恤”,之后调用父类的Display()方法,父类的Display()方法操作是component对象调用Display(),也就是$dtx的component对象$kk调用Display()方法;
$kk调用自身的Display()方法,输出“跨裤”,之后调用父类的Display()方法,父类的Display()方法操作是component对象调用Display(),也就是$kk的component对象$pqx调用Display()方法;
$pqx调用自身的Display()方法,输出“破球鞋”,之后调用父类的Display()方法,父类的Display()方法操作是component对象调用Display(),也就是$pqx的component对象$Person调用Display()方法;
$Person调用自身的Display()方法,输出“装饰的: 某某某”结束。

适用场景:
1. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
2. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。
3. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.m或d论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PeakXin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值