设计模式之装饰者模式

 

 

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类都是使用了装饰者模式。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值