Java设计模式之装饰者模式
一、定义装饰对象
/*
* 定义一个装饰对象Person。
* 包含一个方法feature()。
* */
class Person{
public void feature(){
System.out.println("I am a Person");
}
}
二、定义装饰器
/*
* 定义装饰对象的装饰器PersonDecorator。
* 其中有一个通用的装饰对象引用Person p。
* 有参构造器使p指向参数所表示的Person装饰者对象。
* 有一个feature()方法调用p引用中的feature()方法。
* */
class PersonDecorator extends Person{
public Person p;
public PersonDecorator(Person p){
this.p = p;
}
public void feature(){
p.feature();
}
}
三、定义装饰者对象
/*
* 定义装饰者对象Cloth,Shoe。
* 其有参构造器传入一个Person对象引用并上传到父类装饰器。
* */
class Cloth extends PersonDecorator{
public Cloth(Person p){
super(p);
}
public void feature(){
super.feature();
System.out.println("I wear a cloth");
}
}
class Shoe extends PersonDecorator{
public Shoe(Person p){
super(p);
}
public void feature(){
super.feature();
System.out.println("I wear a shoe");
}
}
四、测试代码
public class Decatcor {
public static void main(String[] args) {
Person p = new Shoe(new Cloth(new Person()));
p.feature();
}
}
/*
*output:
*I am a Person
*I wear a cloth
*I wear a shoe
*/
五、解析
装饰者模式的精髓就在装饰器对象上,通过上述代码可以看到装饰器PersonDecorator有一个通用的Person引用并且在每个子类构造器中通过super(p)使它都指向了当前装饰者对象。
子类装饰者有参构造器
public Cloth(Person p){
super(p);
}
父类装饰器有参构造器
public PersonDecorator(Person p){
this.p = p;
}
又由于每一个装饰者对象的feature()方法都调用了父类的feature()方法,也就是说它会先调用传入它构造器中装饰者对象的feature()方法,
public void feature(){
super.feature();
System.out.println("I wear a shoe");
}
Person p = new Shoe(new Cloth(new Person()))
所以这段代码可以看成这样,相当于递归。我们从new Person()开始,一直到new Shoe()结束,然后在new Shoe()的feature()方法中会返回调用每一个构造器传入的装饰者对象feature()方法。
注意:并不是一定要按照测试代码中实例化的顺序,因为每一个子类装饰者的构造器都是可以接受Person对象参数的,所以装饰者对象之间的顺序可以多样,相应的输出的顺序也会发生改变。
我们再来好好看看这段装饰器对象代码,其实装饰器对象就像是一个连接口,它将你想要实现的不同装饰功能连接到一起,
就像是IO流里面的Filteroutputstream和Filterinputstream,它是譬如BufferArraystream和Dataoutputstream等装饰流的父类装饰器,要想使你的流具有缓冲和输出基础类型只需要像上述测试代码的写法对Outputstream进行装饰。
/*
* 定义装饰对象的装饰器PersonDecorator。
* 其中有一个通用的装饰对象引用Person p。
* 有参构造器使p指向参数所表示的Person装饰者对象。
* 有一个feature()方法调用p引用中的feature()方法。
* */
class PersonDecorator extends Person{
public Person p;
public PersonDecorator(Person p){
this.p = p;
}
public void feature(){
p.feature();
}
}