您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

关于Symfony2中的设计模式:装饰者模式

2025/8/10 13:05:27发布18次查看
在没有接触设计模式时,都是针对具体实现编程,读取数据库新闻时直接写一个基于数据库的方法,读取推荐新闻时再写一个基于xml的方法,两种方法之间没有任何的关系.当时觉的这样实现也没什么不好。可是你总会发现这两种方法在实现上有很多相同的地方,都是读取出一个新闻标题集合来绑定数据源,只是取数据源的方法不同而已。为了方便管理,我们可以定义一个统一的接口来约束这两种方法。这种做法也足够满足读取不同载体的新闻要求。可是如果在读取新闻时要做其它的操作呢?例如:给读取出来的新闻的人气加一。这个时候我们就要修改原程序,这样有背于对扩展开放,对修改关闭的编程原则。如何解决呢?这就是装饰者模式出场的时候了。
在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
装饰者模式把每个要装饰的功能放在单独的类中,并让这个类包装它要装饰的对象,因此,当需要执行特殊行为时,客户端代码就可以在运行的时候根据需要有选择地、按顺序地使用装饰功能包装对象了。
图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 '
'; 15 16 // 用underwear类装饰person 17 $underwear = new underwear($jc); 18 $underwear->show(); // 我是学生jc,穿着dk 19 echo '
'; 20 21 // 再用pants类装饰person 22 $pants = new pants($underwear); 23 $pants->show(); // 我是学生jc,穿着dk,穿着裤子 24 echo '
'; 25 26 // 再用shirt类装饰person 27 $shirt = new shirt($pants); 28 $shirt->show(); // 我是学生jc,穿着dk,穿着裤子,穿着衬衫 29 echo '
'; 30 31 // 再用glasses类装饰person 32 $glasses = new glasses($shirt); 33 $glasses->show(); // 我是学生jc,穿着dk,穿着裤子,穿着衬衫,带着眼镜 34 echo '
';
图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 }
优点
 通过组合而非继承的方式,实现了动态扩展对象的功能的能力。 有效避免了使用继承的方式扩展对象功能而带来的灵活性差,子类无限制扩张的问题。 充分利用了继承和组合的长处和短处,在灵活性和扩展性之间找到完美的平衡点。  装饰者和被装饰者之间虽然都是同一类型,但是它们彼此是完全独立并可以各自独立任意改变的。 遵守大部分grasp原则和常用设计原则,高内聚、低偶合。 缺点
装饰链不能过长,否则会影响效率。 只在必要的时候使用装饰者模式,否则会提高程序的复杂性,增加系统维护难度。 装饰者对象和被装饰者对象都继承component,如果component内部发生变化,所有的子类都要改变。 以上就介绍了关于symfony2中的设计模式:装饰者模式,包括了symfony2,装饰者模式方面的内容,希望对php教程有兴趣的朋友有所帮助。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product