一天一个设计模式---装饰者模式

优点:它可以动态为对象添加功能。

场景:我们希望为某个对象而不是整个类添加一些功能。

一、角色及作用

装饰者和被装饰者拥有相同的组件接口。被装饰者是系统的核心组件,完成特定功能。装饰者则可以在被装饰者的方法前后,加上特定的前置处理和后置处理,增强被装饰者的功能(怎么和代理模式好像!_!,一脸懵逼)

角色作用
组件接口为装饰者和被装饰者的超类或接口。定义被装饰者的核心功能,以及装饰者需要加强的功能
具体组件(被装饰者)实现组件接口的的核心方法,完成具体业务逻辑
装饰者实现组件接口,持有一个被装饰对象
具体装饰者具体实现装饰的业务逻辑。各个具体装饰者是可以相互叠加的

二、装饰者模式

场景:奶茶哥哥的奶茶店开张了,我们推出了两种产品—奶茶和茶叶茶。我们的饮料需要实现自己的描述和自己的价格。

// 饮料的基类(组件接口)
public interface Beverage {

    public String getDescription();

    public double cost();
}
// 奶茶(被装饰者)
public class Milk implements Beverage {

    @Override
    public double cost() {
        return .56;
    }

    @Override
    public String getDescription() {
        return "Milk";
    }
}
// 茶叶茶(被装饰者)
public class Tea implements Beverage {

    @Override
    public double cost() {
        return 1.44;
    }

    @Override
    public String getDescription() {
        return "Tea";
    }

}

奶茶店开张后,我们的饮料很畅销,但是没有新的产品是无法满足客户的。于是,我们研制了调料,让我们的饮料喝起来味道更好。

// 调料的基类(装饰者)
public abstract class CondimentDecorator implements Beverage {
    Beverage beverage;

    public CondimentDecorator(Beverage beberage) {
        this.beverage = beberage;
    }

}
// 抹茶粉(具体装饰者)
public class Matcha extends CondimentDecorator {

    public Matcha(Beverage beberage) {
        super(beberage);
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",Matcha";
    }

    @Override
    public double cost() {
        return .5 + beverage.cost();
    }

}
// 珍珠(具体装饰者)
public class Pearl extends CondimentDecorator {

    public Pearl(Beverage beberage) {
        super(beberage);
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",Pearl";
    }

    @Override
    public double cost() {
        return .2 + beverage.cost();
    }

}

现在我们提供奶茶的方法如下:

    public static void main(String[] args) {
        Beverage be = new Tea();
        System.out.println(be.getDescription() + "---" + be.cost());
        Beverage b2 = new Pearl(new Milk());
        System.out.println(b2.getDescription() + "---" + b2.cost());
        b2 = new Matcha(b2);
        System.out.println(b2.getDescription() + "---" + b2.cost());
    }

输出如下:

Tea---1.44
Milk,Pearl---0.76
Milk,Pearl,Matcha---1.26

可见,我们根据所需要的饮料和调料,奶茶哥哥就提供对应的饮料和价格数据。

三、装饰者模式和代理模式的区别

首先,这两个模式真心在实现上太像了,都是对业务处理的前后增加前置后置的实现。网上找了很多人对这两者的理解,这里总结下我的看法。

装饰模式:
- 以对客户端透明的方式扩展对象的功能
- 可以说是继承关系的一个替代方案
- 用户更关心装饰后的功能

比如上面的奶茶,用户希望得到的是—奶茶+珍珠+抹茶,以及他们的总价

代理模式:
- 代理模式对代理的对象施加控制,并不提供对象本身的增强功能
- 用户通过代理来访问目标的功能,使用者关心的是原始功能都有什么功能,而对于代理的时候的处理却不知道

比如在代理模式中提到的成龙大哥和经纪人的例子,我们更加关心的应该是成龙大哥演戏,而不是经纪人对业务的处理。


更多模式: 一天一个设计模式—分类与六大原则

更多源码: https://github.com/oDevilo/Java-Base

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值