装饰者模式
定义
先上定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式。
优缺点
优点:
1,装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用
2,通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果
3,装饰器模式完全遵守开闭原则
缺点:
装饰模式会增加许多子类,过度使用会增加程序得复杂性,维护起来比较困难
使用场景
用户在不知道内部构建细节的情况下,可以精细的控制对象的构造流程。
当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时采用继承关系很难实现,而采用装饰模式却很好实现。
解构
装饰者模式的结构和使用:
- 抽象构件(Component)角色:它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
- 具体构件(ContextImpl)角色:它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
- 抽象装饰(Decorator)角色:它也是抽象构件类的子类,抽象装饰类不一定是抽象方法。用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
- 具体装饰(ConcreteDecorator)角色:它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。
上图:
举例说明
talk is cheap,show me the code;
上代码:
现在小伙伴都喜欢喝奶茶,那么就用奶茶举个例子,奶茶有很多口味,比如红豆,椰果,我的最爱芒果等;
奶茶抽象类:
public abstract class AbstractMilkyTea {
public abstract String getContent();
public abstract double getPrice();
}
基础的奶茶类:
public class BaseMilkyTea extends AbstractMilkyTea{
@Override
public String getContent() {
return "MilkyTea";
}
@Override
public double getPrice() {
return 10.00;
}
}
抽象装饰类:
public abstract class AbstractDecorator extends AbstractMilkyTea {
private AbstractMilkyTea baseMilkyTea;
public AbstractDecorator(AbstractMilkyTea baseMilkyTea) {
this.baseMilkyTea = baseMilkyTea;
}
@Override
public String getContent() {
return baseMilkyTea.getContent();
}
@Override
public double getPrice() {
return baseMilkyTea.getPrice();
}
}
红豆奶茶类:
public class ReadBeanDecorator extends AbstractDecorator{
public ReadBeanDecorator(AbstractMilkyTea baseMilkyTea) {
super(baseMilkyTea);
}
@Override
public String getContent() {
return super.getContent()+"read bean";
}
@Override
public double getPrice() {
return super.getPrice()+2;
}
}
椰果奶茶类:
public class CoconutDecorator extends AbstractDecorator{
public CoconutDecorator(AbstractMilkyTea baseMilkyTea) {
super(baseMilkyTea);
}
@Override
public String getContent() {
return super.getContent()+"coconut";
}
@Override
public double getPrice() {
return super.getPrice()+3;
}
}
芒果奶茶类:
public class MangoDecorator extends AbstractDecorator{
public MangoDecorator(AbstractMilkyTea baseMilkyTea) {
super(baseMilkyTea);
}
@Override
public String getContent() {
return super.getContent()+"Mango";
}
@Override
public double getPrice() {
return super.getPrice()+5;
}
}
测试代码:
baseMilkyTea = new MangoDecorator(baseMilkyTea);
System.out.println(baseMilkyTea.getPrice());
System.out.println(baseMilkyTea.getContent());
Android Context举例分析
接下来我们通过Android 中的Context的类图,来了解下装饰者模式,对Android开发者应该更直观一些。
在架构设计时,应多用组合,少用继承,同时对扩展开放,对修改关闭;
上个简单的图:
Context就是抽象构件,ContextImpl作为具体构件,ContextWrapper是抽象装饰类,Service,Application就是具体装饰类;
在startActivity时候,会调用系统的handleLaunchActivity方法,接着调用performLaunchActivity方法。其中会创建一个ContextImpl. 然后activity.attach(ContextImpl)将ContextImpl赋予ContextWrapper的mBase。ContextWrapper中的所有行为全都通过mBase去实现。同时ContextWrapper通过具体的子类扩展方法不同的行为,实现对context的装饰和功能扩展。这里就不具体的展开了。