还依然清晰的记得以前上小学时,每次月考考试卷都要给家长签字,分数考得高时就不担心签名的问题,但是常在岸边走哪有不湿鞋,总有那么几次考不好,然后成绩波动太大,此时给家长签字时轻则一顿逼逼,重则一顿挨揍(当然不是狼妈虎爸一样,一天一顿打,孩子上北大)。有时为了避免这波暴击伤害,我们经常会把分数改一下(65就加一笔变成85)或者说找个理由(试卷太难,大家分数都不高等)。下面有程序猿的语言来描述这段经历。
抽象成绩单:
public abstract class GradeReport
{
//向家长汇报
public abstract void report();
//家长签名
public abstract void sign(String name);
}
具体成绩单:
public class MyReport extends GradeReport
{
@Override
public void report()
{
// TODO Auto-generated method stub
System.out.println("xxxx的家长,xxxx同学的总成绩180分(试卷总分300分)");
}
@Override
public void sign(String name)
{
// TODO Auto-generated method stub
System.out.println("家长姓名:"+name);
}
}
抽象装饰类(在怎么装饰他还是一张成绩单)
public abstract class Decorate extends GradeReport
{
GradeReport gradeReport;
public Decorate(GradeReport gradeReport)
{
this.gradeReport = gradeReport;
}
@Override
public void report()
{
this.gradeReport.report();
}
@Override
public void sign(String name)
{
this.gradeReport.sign(name);
}
}
具体装饰类:
public class MyDecorate extends Decorate
{
public MyDecorate(GradeReport gradeReport)
{
super(gradeReport);
// TODO Auto-generated constructor stub
}
public void highReport()
{
System.out.println("由于本次试卷难度比较大,180分已经是不错了");
}
@Override
public void report()
{
// TODO Auto-generated method stub
super.report();
this.highReport();
}
}
场景类:
public class Client
{
public static void main(String[] args)
{
GradeReport report = new MyReport();
Decorate decorate = new MyDecorate(report);
decorate.report();
decorate.sign("xx的家长");
}
}
运行结果:
xxxx的家长,xxxx同学的总成绩180分(试卷总分300分)
由于本次试卷难度比较大,180分已经是不错了
家长姓名:xx的家长
修饰之前只打印出总成绩为180分,想一下小学生300分只考了180很烂了,签名之前绝对少不了一顿逼逼,通过装饰家长很乐意就签上了大名,如果我们需要修饰一下总分排名为班级前列,那么我们只需要重新自定义一个Decorate类就可以实现,这就是装饰模式。
装饰模式定义
装饰模式:Attach additional responsibilties to an object dynamically keeping the same interface. Decorate provider a flexible alternative to subclassing for extending functionality.(动态的给一个对象附加一些额外的职责。就增加新功能来说,装饰模式比生成子类更灵活)。
装饰模式的角色
抽象构件Component:通常是一个接口或者抽象类,定义我们的核心对象,也是最原始的对象,比如我们上面的原始成绩单。
具体构建ConcreteComponent:最原始、最基本的抽象类或接口的实现,我们需要装饰的就是他。比如例子中的MyGradeReport。
抽象装饰角色:属性中存在一个Component的引用。
具体装饰角色:就是我们需要给ConcreteComponent装饰的东西都在这,上面的例子就是把查成绩单装饰成家长能接受的成绩单。
装饰模式的优点:
1.装饰类和被装饰类独立发展不耦合,原始成绩单不需要知道装饰类,装饰类是从外部进行扩充。
2.装饰模式是继承的一种替代方案,不管装饰了多少次,他最终还是一张成绩单。
3.装饰模式可以动态的扩展实现类的功能。
装饰模式的缺点:
装饰层数多了,如果最里层的装饰类出了问题,那么追踪问题就会非常复杂,需要像剥洋葱一样一层层往里排查,增加了系统的复杂度。