优点:它可以动态为对象添加功能。
场景:我们希望为某个对象而不是整个类添加一些功能。
一、角色及作用
装饰者和被装饰者拥有相同的组件接口。被装饰者是系统的核心组件,完成特定功能。装饰者则可以在被装饰者的方法前后,加上特定的前置处理和后置处理,增强被装饰者的功能(怎么和代理模式好像!_!,一脸懵逼)
角色 | 作用 |
---|---|
组件接口 | 为装饰者和被装饰者的超类或接口。定义被装饰者的核心功能,以及装饰者需要加强的功能 |
具体组件(被装饰者) | 实现组件接口的的核心方法,完成具体业务逻辑 |
装饰者 | 实现组件接口,持有一个被装饰对象 |
具体装饰者 | 具体实现装饰的业务逻辑。各个具体装饰者是可以相互叠加的 |
二、装饰者模式
场景:奶茶哥哥的奶茶店开张了,我们推出了两种产品—奶茶和茶叶茶。我们的饮料需要实现自己的描述和自己的价格。
// 饮料的基类(组件接口)
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
可见,我们根据所需要的饮料和调料,奶茶哥哥就提供对应的饮料和价格数据。
三、装饰者模式和代理模式的区别
首先,这两个模式真心在实现上太像了,都是对业务处理的前后增加前置后置的实现。网上找了很多人对这两者的理解,这里总结下我的看法。
装饰模式:
- 以对客户端透明的方式扩展对象的功能
- 可以说是继承关系的一个替代方案
- 用户更关心装饰后的功能
比如上面的奶茶,用户希望得到的是—奶茶+珍珠+抹茶,以及他们的总价
代理模式:
- 代理模式对代理的对象施加控制,并不提供对象本身的增强功能
- 用户通过代理来访问目标的功能,使用者关心的是原始功能都有什么功能,而对于代理的时候的处理却不知道
比如在代理模式中提到的成龙大哥和经纪人的例子,我们更加关心的应该是成龙大哥演戏,而不是经纪人对业务的处理。
更多模式: 一天一个设计模式—分类与六大原则