php面向对象进阶设计模式:装饰器模式
如果对已有对象的部分内或功能性发生改变,但是不需要修改原始对象的结构,那么使用装饰器设计模式最适合。
装饰器模式应用问题与解决方案:
我们最开始学习面向对象编程的相关知识时,第一个障碍往往是理解继承当中的父子关系。随着时间的推移,我们会更加熟悉这种编程方法。当面对新的挑战时,经验丰富的面向对象编程人员会立即为某个对象扩展更多的功能。不过,正如万物皆有度,只有适度的使用才能保证这种工作的良好开展。
代码库应当对类层次的数量有限制。如果对象开始要求启用过多的子类,那么相应的代码就会牺牲编程人员的理解力和可维护性。通常,我竭力保证用于一个对象的父子关系不超过3个。我发现:只要创建较多的父子关系,那么代码就会变得混乱和难以控制。除此之外,使用一般的纸张也无法答应出应用程序中任何对象的UML图表示。
不过,我并不希望阻止类扩展的使用。实际上,我们经常使用适当的解决方案来扩展对象。但是,对于某些问题来说,使用基于装饰器设计模式的类是更好的解决方案。
装饰器设计模式适用于编程人员话费大量时间所处的下列工作场合:变化是快速和细小的,而且几乎不影响应用程序的其余部分。使用装饰器设计模式设计类的目标是:不必重写任何已有的功能性,而是对某个基对象应用增量变化。装饰器采用这样的构建方式:在主代码流中应当能够直接插入一个或多个更改或“装饰”目标对象的装饰器,同时不影响其他代码流。
UML
下UML图详细说明了一个使用装饰器设计模式的类设计。
下面对上图的说明:
1.MyObject是具有现有功能性的基类。这个类包含名为items的公共数组和名为show ItemsFormatted()的公共方法。
2.show ItemsFormatted()方法负责接受items数组,并且使用预定义的功能性格式化该数组后提交输出。
3.MyObjectDecorator类包含MyObject的一个私有实例和两个公共方法:MyObjectDecorator()和decorateItems()。
4.MyObjectDecorator()方法代表构造函数,它接受一个MyObject类型参数并将其存储在内部。
5.decorateItems()方法可修改MyObject实例的items数组。
我们来看下面这个例子,为了计算一块区域的价值,我们把代码写成下面这个样子:
// 区域抽象类 abstract class Area { abstract public function treasure(); } //森林类,价值100 class Forest extends Area { public function treasure() { return 100; } } //沙漠类,价值10 class Desert extends Area { function function treasure() { return 10; } }
上面的代码看上去好像没有什么问题,但是如果需要给一片被破坏的森林计算价值怎么办呢,添加DamageForest子类么?显然是不可行的,因为很有可能还有其他很多类型叠加的类,这会导致类中可能会有重复的代码,且子类也会变的越来越多。
装饰器模式使用组合和委托,而不是使用继承来解决上述的问题,我们在来看下面改良过的代码:
// 区域抽象类 abstract class Area { abstract public function treasure(); } //森林类,价值100 class Forest extends Area { public function treasure() { return 100; } } //沙漠类,价值10 class Desert extends Area { function function treasure() { return 10; } } //区域类的装饰器类 abstract class AreaDecorateor extends Area { protected $_area = null; public function __construct(Area $area) { $this->_area = $area; } } //被破坏了后的区域,价值只有之前的一半 class Damaged extends AreaDecorateor { public function treasure() { return $this->_area->treasure() * 0.5; } } //现在我们来获取被破坏的森林类的价值 $damageForest = new Damaged(new Forest()); echo $damageForest->treasure(); //返回50
以上就是php面向对象进阶设计模式:装饰器模式的详细内容,更多请关注其它相关文章!
上一篇: PHP使用curl函数发送Post请求的注意事项实例详解
下一篇: Python3 文件操作详解