1模式定义
通过包装一个装饰对象来动态的扩展其功能(添加功能),且又不需要改变装饰对象的接口(即:在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能)
2应用场景
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。
3组成部分
- 抽象组件(Component) :定义装饰方法的规范
- 被装饰者(ConcreteComponent) :Component的具体实现,也就是我们要装饰的具体对象。
- 装饰者组件(Decorator) :持有组件(Component)对象的实例引用,该类的职责就是为了装饰具体组件对象,定义的规范。
- 具体装饰(ConcreteDecorator) :负责给构件对象装饰附加的功能。
4 示例场景说明
装饰者模式之 – inputStream
- 抽象组件(InputStream) :装饰者模式中的超类,它只有一个抽象方法read(),子类都需要对该方法进行处理
- 被装饰者(FileInputStream , ByteArrayInputStream , StringBufferInputStream) :拥有通用实现read()基本方法
- 装饰者组件(FilterInputStream) :定义具体装饰者的行为规范,可以做统一基础处理。
- 具体装饰(BufferedInputStream , DataInputStream , Base64InputStream) :具体的装饰类,拥有对流的读操作做完成具体拓展能力。
装饰者模式让我们可以有不同的被装饰者,例如FileInputStream,并且如果想使用缓冲功能那么只需写一下代码 : new BufferedInputStream(new FileInputStream(new File("path")));
也可以对上面代码再进行加工,简单的加密处理 new Base64InputStream(new BufferedInputStream(new FileInputStream(new File(""))),0)
哪怕你突然改需求了,读取的对象不是文件,而是文本或字符,那么可以轻松的将代码改为 :new Base64InputStream(new BufferedInputStream(new StringBufferInputStream("str")),0)
5 示例代码
5.1//抽象组件
public interface Component {
public void methond();
}
5.2//待装饰者(被装饰者)
public class ConcreteComponent implements Component {
@Override
public void methond() {
// TODO Auto-generated method stub
System.out.println("ConcreteComponent::methond");
}
}
5.3 //抽象装饰者组件
public abstract class Decorator implements Component {
public Component mComponent;
public Decorator(Component mComponent){
this.mComponent = mComponent;
}
@Override
public void methond() {
// TODO Auto-generated method stub
mComponent.methond();
}
}
5.4.1//具体的装饰A
public class DecoratorA extends Decorator {
public DecoratorA(Component mComponent) {
super(mComponent);
// TODO Auto-generated constructor stub
}
@Override
public void methond() {
// TODO Auto-generated method stub
methondA1();
super.methond();
methondA2();
}
public void methondA1(){
System.out.println("DecoratorA:: methondA1()");
}
public void methondA2(){
System.out.println("DecoratorA:: methondA2()");
}
}
5.4.2//具体的装饰B
package decorate;
public class DecoratorB extends Decorator {
public DecoratorB(Component mComponent) {
super(mComponent);
// TODO Auto-generated constructor stub
}
@Override
public void methond() {
// TODO Auto-generated method stub
methondB1();
super.methond();
methondB2();
}
public void methondB1(){
System.out.println("DecoratorB::methondB1()");
}
public void methondB2(){
System.out.println("DecoratorB::methondB2()");
}
}
装饰者特征:一:拥有被装饰者对象,二:透明的拓展原本的方法
5.5 //客户测试类
public class ClientDecorate {
public static void main(String[] args) {
ConcreteComponent cc = new ConcreteComponent();
DecoratorA aa = new DecoratorA(cc);
aa.methond();
aa.methondA1();
aa.methondA2();
System.out.println("----------------------");
DecoratorB bb = new DecoratorB(cc);
bb.methond();
bb.methondB1();
bb.methondB2();
System.out.println("----------------------");
bb = new DecoratorB(aa);
bb.methond();
bb.methondB1();
}
}
结果输出:
6 总结:
7Android源码模式分析
Android中的ContextWrapper
待续....
- 装饰者和被装饰者有相同的超类(Component)。
- 你可以用一个或多个具体装饰(ConcreteDecorator)包装一个对象。
- 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的。(类似代理模式)
- 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
- Component接口可以是接口也可以是抽象类,甚至是一个普通的父类(这个强烈不推荐,普通的类作为继承体系的超级父类不易于维护)
- 装饰器的抽象父类Decorator并不是必须的。
站在巨人的肩膀,参考文献:
https://blog.csdn.net/qian520ao/article/details/82529890