引入
1.案例
比如,三个继承关系:Father,Son,GrandSon三个类,我要在son类上增加一些功能怎么办?
2.面向实现编程方案
修改Son,这种方案会有大问题,因为你增强的功能是是修改Son的方法还是增加Son的方法,是否会对GrandSon造成影响呢?
3.面向设计编程方案
通过建立SonDecorator类来修饰Son类,相当于创建了一个新的类,这个对原有程序没有改变,通过扩展很好的完成了这次变更。
其实下面的代码案例并不是非常好,容易让人理解错误。以改需求为例:
建立SonDecorator,把Son的对象传递给SonDecorator,这样可以保证Son的功能不会丢失,然后在SonDecorator中增加一个新的功能即可,比如新增加一个方法a(),这个方法是和Son没有关系的。
一.名称
二.问题(为了解决什么问题)
- 一个子系统需要对外提供服务
- 需要扩展一个类的功能,或给一个类增加附加功能。
- 需要动态的给一个对象增加功能,这些功能可以再动态地撤销。
- 需要为一批的兄弟类进行改装或加装功能,当然是首选装饰模式。
三.解决方案(主要体现在uml和核心代码上)
装饰模式是对继承的有力补充,你要知道继承不是万能的,继承可以解决实际的问题,但是在项目中你要考虑诸如易维护、易扩展、易复用等,而且在一些情况下(比如上面那个成绩单例子)你要是用继承就会增加很多子类,而且灵活性非常差。而装饰模式就有一个非常好的优点:扩展性非常好。
装饰者模式主要体现的扩展,通过包一层来扩展(与增加一层类似)。
体现的原则:无
通用代码:
四.例子
成绩单装饰:
基本类:
/**
* Created by annuoaichengzhang on 16/3/26.
*/
public abstract class SchoolReport {
public abstract void report();
public abstract void sign(String name);
}
装饰类:
/**
* Created by annuoaichengzhang on 16/3/26.
*/
public class Decorator extends SchoolReport {
private SchoolReport sr;
public Decorator(SchoolReport sr) {
this.sr = sr;
}
// 保证装饰者类还有SchoolReport的功能
@Override
public void report() {
this.sr.report();
}
@Override
public void sign(String name) {
this.sr.sign(name);
}
}
/**
* Created by annuoaichengzhang on 16/3/26.
*/
public class HightScoreDecorator extends Decorator {
public HightScoreDecorator(SchoolReport sr) {
super(sr);
}
@Override
public void report() {
super.report();
}
// 装饰者类新增加的功能
private void reportHightScore() {
System.out.println("这次语文最高是75,数学是78,自然是80");
}
}
/**
* Created by annuoaichengzhang on 16/3/26.
*/
public class SortDecorator extends Decorator {
public SortDecorator(SchoolReport sr) {
super(sr);
}
// 装饰者类新增加的功能
private void reportSort() {
System.out.println("我的排名第38名.....");
}
@Override
public void report() {
super.report();
}
}
Client:
public class Client {
public static void main(String[] args) {
SchoolReport sr = null;
sr = new FouthGradeSchoolReport();
sr = new HightScoreDecorator(sr);
sr.reportHightScore();
sr = new SortDecorator(sr);
sr.sign("老爸");
}
}
五.效果(有啥优缺点)
常见案例
带滚动条的窗体
多重数据加密系统。用户使用最简单的加密算法觉得不行,还可以吧加密后的结果使用其他加密算法进行二次加密,当然也可以进行三次加密。