装饰者模式
定义
动态地给一个对象添加一些额外的职责。就增加功能来说,装饰者模式相比生成子类更灵活
优缺点和应用场景
优点
- 拓展某个类的功能,附加功能
- 动态地给一个对象增加功能,这些功能可以动态地撤销
- 需要给一批兄弟类进行改装或加装功能
缺点
- 装饰的细节不宜过多,否则很难把控执行公用方法的切入点(比如一个类对原类进行装饰后,第二个类就只能在前一个类的基础上再装饰,这样就还需要考虑第一次装饰后的组合结果)
- 因为装饰的结构是由内向外,如果内层出现修改,就会影响外层的结果(有可能埋下大坑)。
使用场景
- 需要拓展一个类的功能,或给一个类增加附加功能
- 需要动态地给一个对象增加功能,这些功能可以再动态地撤销
- 需要为一批兄弟类进行改装或加装功能,首选装饰模式
成绩单抽象及细节
/**
* 抽象成绩单
*/
public abstract class SchoolReport {
// 成绩单上主要展示成绩信息
public abstract void report();
// 家长签名信息
public abstract void sign(String name);
}
/**
* 本次考试的成绩单
*/
public class FourthSchoolReport extends SchoolReport {
@Override
public void report() {
System.out.println("尊敬的XXX的家长:");
System.out.println("\t.......");
System.out.println("\t语文-62\t数学-65\t体育-98\t自然-63");
System.out.println("\t.......");
System.out.println("\t\t\t\t\t家长签名:");
}
@Override
public void sign(String name) {
System.out.println("家长签名为:" + name);
}
}
场景一:硬核的给成绩单装饰(但这种用法往往最实在)
硬核装饰类
/**
* 硬核装饰类
*/
public class SugarFourthGradeSchoolReport extends FourthSchoolReport {
// 首先定义要美化的方法,先说班级最高的成绩
private void reportHighScore() {
System.out.println("这次语文最高分75,数学78,自然是80");
}
// 再汇报班级排名情况
public void reportSort(){
System.out.println("我的排名是:38");
}
// 重写父类中的report
@Override
public void report() {
this.reportHighScore();
super.report();
this.reportSort();
}
}
结果
场景二:抽象出一个装饰器,装饰细节都由它管
装饰者(抽象)
public abstract class Decorator extends SchoolReport {
// 首先知道装饰的是哪个成绩单
private SchoolReport sr;
// 传一个成绩单过来
public Decorator(SchoolReport sr){
this.sr = sr;
}
// 统一重写父类中的方法
@Override
public void report() {
this.sr.report();
}
@Override
public void sign(String name) {
this.sr.sign(name);
}
}
装饰者实例
/**
* 最高成绩装饰类
*/
public class HighScoreDecorator extends Decorator {
public HighScoreDecorator(SchoolReport sr) {
super(sr);
}
// 汇报最高成绩
private void reportHighScore(){
System.out.println("这次考试语文最高75,数学78,自然80");
}
@Override
public void report() {
this.reportHighScore();
super.report();
}
}
/**
* 排名情况装饰
*/
public class SortDecorator extends Decorator {
public SortDecorator(SchoolReport sr) {
super(sr);
}
// 班级排名
private void reportSort() {
System.out.println("我的排名是:38");
}
@Override
public void report() {
super.report();
this.reportSort();
}
}
入口类
public class DecoratorMain {
public static void main(String[] args) {
// noDecorator();
// hardcoreExtends();
decorator();
}
// 装饰者组件负责灵活组合多个装饰配置
public static void decorator(){
SchoolReport sr;
// 原装成绩单
sr = new FourthSchoolReport();
// 加上排名说明
sr = new SortDecorator(sr);
// 加上最高分说明
sr = new HighScoreDecorator(sr);
sr.report();
sr.sign("Yeah~");
}
// 继承类形式的硬核装饰
public static void hardcoreExtends(){
SchoolReport report = new SugarFourthGradeSchoolReport();
report.report(); // 老爸看到装饰后成绩单很高兴
report.sign("Yeah~");
}
// 没有任何装饰
public static void noDecorator(){
// 模拟父亲行为,愤怒在积攒
SchoolReport report = new FourthSchoolReport();
report.report();
// 签名是不可能签名的了
}
}
结果
参考书籍
秦小波《设计模式之禅》