PHP头条
热点:

Symfony2中的设计模式——装饰者模式,symfony2设计模式


装饰者模式的定义

  在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

  装饰者模式把每个要装饰的功能放在单独的类中,并让这个类包装它要装饰的对象,因此,当需要执行特殊行为时,客户端代码就可以在运行的时候根据需要有选择地、按顺序地使用装饰功能包装对象了。

图1

使用场景

  设想一下,如果我们需要创建一个在不同场合有不同着装的学生,例如:在学校学生需要穿上校服,在舞会学生需要穿上正装,在家学生可以裸装(有点变态),当然,还可以学习超人把底裤穿在外面。这时候问题来了,难道我们要为每种场合编写一个不同穿着的学生类吗?如果我们的童鞋想要一个穿着校服裤子、正装上衣外露的底裤怎么办?StudentWithSchoolUniform、StudentWithFormalWear、StudentWithNaked、StudentWithSchoolUniformAndOutSideUnderWear..................绵绵无尽的类~~~累!是的,如果这样就造成类爆炸了,需求增加,类就不断的增加,整个系统的维护难度可想而知。

  所以这时候,装饰者模式就可以发挥它的作用了,底裤、正装、校服、鞋子、眼镜等等都是具体的装饰者,学生是具体的被装饰的对象,被装饰的对象和装饰者的抽象类都继承者同一个父类。为学生穿上不同的服装,其实就是使用装饰者类(服装)包裹被装饰者类(学生),形象的说这是一个穿衣的过程。

类和接口

  • Component(被装饰对象基类,对应例子的Person类)
  • ConcreteComponent(具体被装饰对象,对应例子的Student类)
  • Decorator(装饰者基类,对应例子的Costume)
  • ContreteDecorator(具体的装饰者类,对应例子的Pants、Shirt等)

例子

图2 

Person.php

1 <?php 2 3 /** 4 * Person.php 5 * 被装饰基类 6 **/ 7 abstract class Person{ 8 9 public abstract function show(); 10 11 } View Code

Student.php

1 <?php 2 3 /** 4 * Student.php 5 * 具体被装饰对象 6 **/ 7 class Student extends Person{ 8 9 private $name; 10 11 public function __construct($name){ 12 $this->name = $name; 13 } 14 15 public function show(){ 16 echo '我是学生',$this->name; 17 } 18 } View Code

Costume.php

1 <?php 2 3 /** 4 * Costume.php 5 * 装饰者基类 6 **/ 7 abstract class Costume extends Person{ 8 9 10 } View Code

Shirt.php

1 <?php 2 3 /** 4 * Shirt.php 5 * 具体的装饰者类 6 **/ 7 class Shirt extends Costume{ 8 9 private $person; 10 11 public function __construct(Person $person){ 12 13 $this->person = $person; 14 15 } 16 17 public function show(){ 18 19 echo $this->person->show(),',穿着衬衫'; 20 } 21 22 } View Code

Pants.php

1 <?php 2 3 /** 4 * Pants.php 5 **/ 6 class Pants extends Costume{ 7 8 private $person; 9 10 public function __construct(Person $person){ 11 12 $this->person = $person; 13 14 } 15 16 public function show(){ 17 18 echo $this->person->show(),',穿着裤子'; 19 } 20 21 } View Code

Glasses.php

1 <?php 2 3 /** 4 * Glasses.php 5 **/ 6 class Glasses extends Costume{ 7 8 private $person; 9 10 public function __construct(Person $person){ 11 12 $this->person = $person; 13 14 } 15 16 public function show(){ 17 18 echo $this->person->show(),',带着眼镜'; 19 } 20 21 } View Code

UnderWear.php

1 <?php 2 3 /** 4 * UnderWear.php 5 **/ 6 class UnderWear extends Costume{ 7 8 private $person; 9 10 public function __construct(Person $person){ 11 12 $this->person = $person; 13 14 } 15 16 public function show(){ 17 18 echo $this->person->show(),',穿着DK'; 19 } 20 21 } View Code

Client.php

 1 <?php
 2 
 3     require_once 'Person.php';
 4     require_once 'Costume.php';
 5     require_once 'Student.php';
 6     require_once 'UnderWear.php';
 7     require_once 'Shirt.php';
 8     require_once 'Pants.php';
 9     require_once 'Glasses.php';
10 
11     // Student继承Person
12     $jc = new Student('JC');
13     $jc->show();   // 我是学生JC
14     echo '<br>';
15 
16     // 用UnderWear类装饰Person
17     $underwear = new UnderWear($jc);
18     $underwear->show();  // 我是学生JC,穿着DK
19     echo '<br>';
20 
21     // 再用Pants类装饰Person
22     $pants = new Pants($underwear);
23     $pants->show();   // 我是学生JC,穿着DK,穿着裤子
24     echo '<br>';
25 
26     // 再用Shirt类装饰Person
27     $shirt = new Shirt($pants);
28     $shirt->show();  // 我是学生JC,穿着DK,穿着裤子,穿着衬衫
29     echo '<br>';
30 
31     // 再用Glasses类装饰Person
32     $glasses = new Glasses($shirt);
33     $glasses->show();  // 我是学生JC,穿着DK,穿着裤子,穿着衬衫,带着眼镜
34     echo '<br>';

图3 输出结果截图

Symfony2 EventDispatch 组件对装饰者模式的应用

 图4 Symfony2 EventDispatch组件使用装饰模式

图5 Framework配置EventDispatcher

 

  • Symfony\Component\EventDispatcher\EventDispatcherInterface 是被装饰的接口
  • Symfony\Component\EventDispatcher\EventDispatcher 和 Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher 是被装饰的具体对象
  • Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface 装饰者接口
  • Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher 装饰者基类
  • Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher 具体的装饰者对象

  具体装饰者对象Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher::dispatch()方法,核心依旧是调用被装饰的具体对象Symfony\Component\EventDispatcher\EventDispatcher::dispatch()方法进行工作,但是装饰者对象Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher::dispatch()方法添加了相应的功能,例如在调用Symfony\Component\EventDispatcher\EventDispatcher::dispatch()方法前后分别调用了preProcess()、preDispatch()和postDispatch()、postProcess():

 1     /**
 2      * {@inheritdoc}
 3      */
 4     public function dispatch($eventName, Event $event = null)
 5     {
 6         if (null === $event) {
 7             $event = new Event();
 8         }
 9 
10         // 装饰者对象增加的功能
11         $this->preProcess($eventName);
12         $this->preDispatch($eventName, $event);
13 
14         $e = $this->stopwatch->start($eventName, 'section');
15 
16         // 核心依旧是调用被装饰的具体对象Symfony\Component\EventDispatcher\EventDispatcher::dispatch()方法
17         $this->dispatcher->dispatch($eventName, $event);
18 
19         if ($e->isStarted()) {
20             $e->stop();
21         }
22 
23         // 装饰者对象增加的功能
24         $this->postDispatch($eventName, $event);
25         $this->postProcess($eventName);
26 
27         return $event;
28     }

 

优点

缺点

www.phpzy.comtrue/php/30125.htmlTechArticleSymfony2中的设计模式——装饰者模式,symfony2设计模式 装饰者模式的定义 在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装...

相关文章

    暂无相关文章

PHP之友评论

今天推荐