装饰者模式

 一、装饰者模式(Decorator Pattern/Wrapper Pattern)的定义
       装饰者模式就是动态地把职责附加到已有对象上去,实现功能扩展。

二、装饰者模式类图
装饰者模式装饰者模式

三、装饰者模式示例代码
在装饰模式中的各个角色有:
抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(Concrete Decorator)角色:负责给构件对象"贴上"附加的责任。
// 抽象类 (抽象构件角色:给出一个抽象接口)
Girlpublic abstract class Girl {
String description = "no particular";
public String getDescription(){
     return description;
}
}
// 美国女孩(具体构件角色:定义一个要接收附加职责的类)
public class AmericanGirl extends Girl {
public AmericanGirl() {
     description = "+AmericanGirl";
}
}
// 国产妹子(具体构件角色)
public class ChineseGirl extends Girl {
public ChineseGirl() {
     description = "+ChineseGirl";
}
}
// 装饰者(装饰角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口)
public abstract class GirlDecorator extends Girl {
     public abstract String getDescription();
}
// 下面以美国女孩示例
// 给美国女孩加上金发(具体装饰角色)
public class GoldenHair extends GirlDecorator {
private Girl girl;
public GoldenHair(Girl g) {
     girl = g;
}
@Override
public String getDescription() {
     return girl.getDescription() + "+with golden hair";
}
}
// 加上身材高大的特性(具体装饰角色)
public class Tall extends GirlDecorator {
private Girl girl;
public Tall(Girl g) {
     girl = g;
}
@Override
public String getDescription() {
     return girl.getDescription() + "+is very tall";
}
}
// 检验一下
public class Test {
public static void main(String[] args) {
Girl g1 = new AmericanGirl();
System.out.println(g1.getDescription());
GoldenHair g2 = new GoldenHair(g1);
System.out.println(g2.getDescription());
Tall g3 = new Tall(g2);
System.out.println(g3.getDescription());
// 你也可以一步到位
// Girl g = new Tall(new GoldenHair(new AmericanGirl()));
}
}

 四、装饰者模式应用
       1、当你需要动态地给一个对象添加功能,实现功能扩展的时候,就可以使用装饰者模式。
       2、Java IO类中有一个景点的装饰者模式应用,BufferedReader 装饰了InputStreamReader.
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
InputStreamReader(InputStream in)——InputStreamReader读取bytes字节内容,然后转换成characters流输出。
BufferedReader(Reader in)——从characters流中读取内容并缓存

五、装饰者模式、适配器模式区别
1、关于新职责:
     适配器也可以在转换时增加新的职责,但其主要目的并不是这个,而装饰者的主要目的就是给被装饰者增加新职责。
2、关于原接口:
     适配器模式是用新接口来调用原接口,原接口对新系统来说是不可见或者说不可用的;而装饰者模式原封不动的使用原接口,系统对装饰对象也通过原接口来完成使用。
3、关于其包裹的对象:
     适配器是知道被适配者的详细情况的;而装饰者只知道其接口是什么,至于其具体类型(是基类还是其他派生类)只有在运行期间才知道。

六、适用场景与优缺点:
在以下情况下应当使用装饰模式:
1.需要扩展一个类的功能,或给一个类增加附加责任。
2.需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
3.需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
优点:
1. Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
缺点:
1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。

参考:
http://blog.****.net/lcl_data/article/details/8830455
https://www.shiyanlou.com/courses/100/labs/874/document