设计模式(11):装饰模式

本章节我们来说一说装饰模式,装饰是什么,从字面上理解就是,装饰一下事物,如果汽车改装,房子装修,都是装饰,那我们就简单给装饰模式下一个定义,让原来的事物变成一个更好更符合我们需求的事物,软件领域里面的定义为:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
怎么理解呢?比如我们有一个 小学生 对象Object 他有一个行为(方法),这个行为是啥呢?,就是报告成绩,加入这个小学生本次考试成绩为 语文 50分 数学 45 分,我靠成绩太差了,但是本次班级的最高分为 语文 52分 数学 49 分 那其实考得也不错,是吧,但是如果你不先说班级最高分,但看这个小学生的成绩确实很差,那我们就装饰一下,在这个小学生报告成绩之前先报告一下班级最高分。
流程如下:
1、报告班级最高分。
2、报告自己的成绩。
那我们要怎么修改呢?,有以下几种方法:
1、最简单的方式修改这个对象的源代码,在报告成绩的method里面,加上报告最高分的步骤。
2、第二种方式那就是新写一个类继承继承小学生类,复写报告成绩的method,在复写的方法里面加上报告最高分的步骤。
这两种方法都是可行知道,但是都有问题,什么问题呢?听我慢慢道来:
第一种方案,修改了小学生类的源码,如果出现那种不需要 先报告班级最高分的小学生,你会发现你强制给人家加上了。
第二种方案,通过继承实现功能添加,很合理,但是有没有想过这个问题,如果还需要添加各种各样的功能,你都一 一继承吗,一般情况下,如果继承超过3层,就要思考自己的设计是否有问题。
那么问题来了,还有其他更优雅的方式吗?当然有了,不然我这篇文章写的下去吗?主角闪亮登场-----装饰模式 ,我们先看看类图:
SchoolReport 就是上述问题中的小学生接口。
FouthGradeSchoolReport 就是上述问题的小学生(我们让他上四年级,所以实现是四年级小学生)。
Decorator 就是我们抽象的装饰者。
HightScoreDecorator 就是具体的先报告班级最高分的装饰者。
SortDecorator 就是具体的 在报告完成绩后 报告排名的装饰者。
Father 就是小学生的父亲,需要听小学生报告成绩。
关系:HightScoreDecorator 装饰FouthGradeSchoolReport
SortDecorator 装饰FouthGradeSchoolReport
FouthGradeSchoolReport 是被装饰的对象。
在不修改小学生的源码以及不通过直接性的继承让小学生报告成绩之前先报告班级最高分。
设计模式(11):装饰模式
具体的代码如下:
代码结构:
设计模式(11):装饰模式
ISchoolReport:
设计模式(11):装饰模式
FouthGradeSchoolReport:
设计模式(11):装饰模式
AbstractDecorator:
设计模式(11):装饰模式
RepotHightGradeDecorator:
设计模式(11):装饰模式
RepotSortDecorator:
设计模式(11):装饰模式
Test: 类似类图中的Father
设计模式(11):装饰模式
小学生报告成绩的问题解决了吧,就是利用了装饰模式,下面来看看装饰模式的通用类图:
设计模式(11):装饰模式
在类图中,有四个角色需要说明:
● Component抽象构件 Component是一个接口或者是抽象类,就是定义我们最核心的对象,也就是最原始的对象,如上面的成绩 单。注意 在装饰模式中,必然有一个最基本、最核心、最原始的接口或抽象类充当Component抽象构件。
● ConcreteComponent 具体构件ConcreteComponent是最核心、最原始、最基本的接口或抽象类的实现,你要装饰的就是它。
● Decorator装饰角色 一般是一个抽象类,做什么用呢?实现接口或者抽象方法,它里面可不一定有抽象的方法呀,在它的属性 里必然有一 个private变量指向Component抽象构件。
● 具体装饰角色 ConcreteDecoratorA和ConcreteDecoratorB是两个具体的装饰类,你要把你最核心的、最原始的、最基本的 东西装饰成其他东西,上面的例子就是把一个比较平庸的成绩单装饰成家长认可的成绩单。
伪代码如下:
Component:
设计模式(11):装饰模式
ConcreteComponent:
设计模式(11):装饰模式
Decorator:
设计模式(11):装饰模式
ConcreteDecorator1:
设计模式(11):装饰模式
ConcreteDecorator2:
设计模式(11):装饰模式
Client:
设计模式(11):装饰模式

总结:
优点:
● 装饰类和被装饰类可以独立发展,而不会相互耦合。换句话说,Component类无须知道Decorator类, Decorator类是从外部来扩展Component类的功能,而Decorator也不用知道具体的构件。
● 装饰模式是继承关系的一个替代方案。我们看装饰类Decorator,不管装饰多少层,返回的对象还是 Component,实现的还是is-a的关系。● 装饰模式可以动态地扩展一个实现类的功能,这不需要多说,装饰模式的定义就是如此。

缺点:
对于装饰模式记住一点就足够了:多层的装饰是比较复杂的。为什么会复杂呢?你想想看,就像剥洋葱一 样,你剥到了最后才发现是最里层的装饰出现了问题,想象一下工作量吧,因此,尽量减少装饰类的数量,以 便降低系统的复杂度。

使用场景:
● 需要扩展一个类的功能,或给一个类增加附加功能。
● 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
● 需要为一批的兄弟类进行改装或加装功能,当然是首选装饰模式。