场景
设计模式-装饰者模式在Java中的使用示例:
设计模式-装饰者模式在Java中的使用示例_java装饰者模式例子-CSDN博客
上面装饰器的调用示例如下
AbstarctComputer computer;
//要买1台电脑
computer = new BaseComputer();
//加一个内存条
computer = new MemoryDecorator(computer);
//加一个硬盘
computer = new DiskDecorator(computer);
//再加一个内存条
computer = new MemoryDecorator(computer);
System.out.println(computer.getMsg()+",总价:"+computer.getPrice());
下面记录一个它的变形,以软件设计师2016年下半年试题六为例
某发票(lnvoice)由抬头(Head)部分、正文部分和脚注(Foot)部分构成。现采用装饰(Decorator)模式实现打印发票的功能,
得到如图6-1所示的类图
注:
博客:
霸道流氓气质-CSDN博客
实现
1、新建发票正文类
public class Invoice {
public void printInvoice(){
System.out.println("This is the content of the invoice !");
}
}
2、新建普通装饰器
public class Decorator extends Invoice{
protected Invoice ticket;
public Decorator(Invoice t){
ticket = t;
}
public void printInvoice(){
if(ticket !=null){
ticket.printInvoice();
}
}
}
3、新建抬头装饰器
public class HeadDecorator extends Decorator{
public HeadDecorator(Invoice t) {
super(t);
}
public void printInvoice(){
System.out.println("This is the header of the invoice!");
super.printInvoice();
}
}
4、新建脚注装饰器
public class FootDecorator extends Decorator{
public FootDecorator(Invoice t) {
super(t);
}
public void printInvoice(){
super.printInvoice();
System.out.println("This is the footnote of the invoice !");
}
}
5、调用示例
Invoice t = new Invoice();
Invoice ticket;
ticket = new HeadDecorator(new FootDecorator(t));
ticket.printInvoice();
System.out.println("----------------------------");
ticket = new HeadDecorator(new FootDecorator(null));
ticket.printInvoice();
以上调用输出结果
This is the header of the invoice!
This is the content of the invoice !
This is the footnote of the invoice !
----------------------------
This is the header of the invoice!
This is the footnote of the invoice !
6、分析
基础回顾
子类创建对象时,会先调用父类的构造方法,然后再调用子类自己的构造方法。
但是,如果子类没有显式地定义构造方法,会使用默认的无参构造方法。
这就是为什么有时候我们需要重写继承的构造方法的原因。
在继承中,子类可以通过super关键字调用父类的构造方法。如果子类没有使用super关键字调用父类的构造方法,
Java会自动调用父类的无参构造方法。如果父类没有提供无参构造方法,且子类没有显示地调用其他构造方法,会导致编译错误
在父类中只有 有参构造函数,没有无参构造函数,子类如果不写构造函数,系统默认创建一个无参构造函数,
子类这个无参的构造函数就会去调用父类的无参构造函数,时候就出错。
以上链式调用时
ticket = new HeadDecorator(new FootDecorator(t));
ticket.printInvoice();
不好理解,可以将其修改为如下便于理解
Invoice t = new Invoice();
t.printInvoice();
FootDecorator footDecorator = new FootDecorator(t);
footDecorator.printInvoice();
Invoice ticket = new HeadDecorator(footDecorator);
ticket.printInvoice();
实现过程分步解析
首先是FootDecorator footDecorator = new FootDecorator(t)
先调用FootDecorator的构造方法,将t(设定地址为Invoice@506)通过构造方法传参传递
并在FootDecorator的构造方法中调用super(t)将其传到父类Decorator的构造方法中进行
protected Invoice ticket的属性的赋值。此时父类Decorator的ticker为Invoice@506
然后将上面新建的footDecorator(设定地址为FootDecorator@509)传递给HeadDecorator的构造方法
此时Invoice t为FootDecorator@509,在其构造方法中通过super(t)调用父类构造方法,并将其赋值给
父类Decorator的protected Invoice ticket,所以此时父类Decorator的ticket为FootDecorator@509
返回值为HeadDecorator的对象(设定为HeadDecorator@511)
然后调用HeadDecorator@511的printInvoice方法
在printInvoice方法中,先输出
This is the header of the invoice!
然后调用父类Decorator的printInvoice方法
此时父类Decorator的ticket为FootDecorator@509,不为空,所以会调用FootDecorator对象FootDecorator@509
的printInvoice方法,方法中会先调用其父类的printInvoice方法,FootDecorator@509父类对象的ticket为Invoice@506
Invoice@506调用printInvoice方法会输出
This is the content of the invoice !
然后FootDecorator@509的printInvoice方法继续输出
This is the footnote of the invoice !