1、装饰者模式
在不改变原有类,需要给类增加新的功能,我们首先想到的是利用继承、AOP。今天讲的装饰者模式是另一种实现思路,它可以避免继承导致子类过多。
装饰者模式(Decorator Pattern),装饰者模式也称为包装模式动态地给一个对象添加一些额外的职责,就增加功能来说,装饰者模式相比生成子类更加灵活,提供了有别于继承的另一种选择。装饰者模式可以静态的,或者根据需要可以动态的在运行时为一个对象扩展功能。被装饰者和众多的装饰者都是继承自一个接口,他们有着一样的行为特性。装饰者模式是继承的另一种选择方式,继承是在编译的时候为类添加新的行为,并且这个改变会影响所有原来该类的实体,装饰者模式就不一样,它提供一种能够在运行时根据需要选择不同运行对象的功能。
2、代码实现
/**
* @Author: WilliamDream
* @Description: 抽象类
* @Date: 2017/12/30 19:19
*/
public abstract class MilkyTea {
protected abstract String getTea();
protected abstract Integer getPrice();
}
/**
* @Author: WilliamDream
* @Description:
* @Date: 2017/12/30 19:21
*/
public class CommonMilkTea extends MilkyTea{
@Override
protected String getTea() {
return "普通原味奶茶";
}
@Override
protected Integer getPrice() {
return 10;
}
}
抽象装饰类,用来装饰被包装者的
/**
* @Author: WilliamDream
* @Description: 抽象的装饰类
* @Date: 2017/8/11 19:21
*/
public abstract class MilkyTeaDecorator extends MilkyTea{
//这里类似静态代理对象
private MilkyTea milkyTea;
//有参的构造函数,将需要包装的对象传进来
public MilkyTeaDecorator(MilkyTea milkyTea){
this.milkyTea = milkyTea;
}
@Override
protected String getTea() {
return this.milkyTea.getTea();
}
@Override
protected Integer getPrice() {
return this.milkyTea.getPrice();
}
}
被包装对象
/**
* @Author: WilliamDream
* @Description:
* @Date: 2017/12/30 19:26
*/
public class PearlMilkyTeaDecorator extends MilkyTeaDecorator{
public PearlMilkyTeaDecorator(MilkyTea milkyTea){
super(milkyTea);
}
@Override
protected String getTea() {
return super.getTea() + "加珍珠";
}
@Override
protected Integer getPrice() {
return super.getPrice() + 1;
}
}
/**
* @Author: WilliamDream
* @Description:
* @Date: 2017/12/30 19:28
*/
public class MangoMilkyTeaDecorator extends MilkyTeaDecorator{
public MangoMilkyTeaDecorator(MilkyTea milkyTea){
super(milkyTea);
}
@Override
protected String getTea() {
return super.getTea() + "加芒果";
}
@Override
protected Integer getPrice() {
return super.getPrice() + 1;
}
}
测试
/**
* @Author: WilliamDream
* @Description:
* @Date: 2017/12/30 19:32
*/
public class DecoratorTest {
public static void main(String[] args) {
MilkyTea milkyTea = new CommonMilkTea();
System.out.println("名字:"+milkyTea.getTea()+"---价格:"+milkyTea.getPrice());
milkyTea = new PearlMilkyTeaDecorator(milkyTea);
System.out.println("名字:"+milkyTea.getTea()+"---价格:"+milkyTea.getPrice());
milkyTea = new MangoMilkyTeaDecorator(milkyTea);
System.out.println("名字:"+milkyTea.getTea()+"---价格:"+milkyTea.getPrice());
//总结:被装饰对象装饰完后还是那个对象,没有变,满足is-a关系,例如不管怎么装饰依然是奶茶
// 跟静态代理不同的是,静态代理是增强功能的,装饰者更多的是扩展,职责不同。
}
}
可以发现实现装饰器模式包含四个角色:1、抽象角色,定义抽象功能,可以是接口或者是抽象类;2、具体构建角色,实现抽象角色;3、抽象的装饰角色,实现抽象角色;4、具体装饰角色,对被装饰对象进行装饰
总结:被装饰对象装饰完后还是那个对象,没有变,满足is-a关系,例如不管怎么装饰依然是奶茶。跟静态代理不同的是,静态代理是增强功能的,装饰者更多的是扩展,职责不同。
装饰者模式在源码中的应用,例如JDK中io相关类,Spring中XXWapper类都是使用了装饰者模式。