一、装饰者模式介绍
装饰者模式(Decorator Pattern):动态地将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性。同时,装饰者模式也体现了开闭原则。
装饰者模式角色:
- 抽象构件(
Component
)角色:给出一个抽象接口,以规范准备接收附加责任的对象。- 具体构件(
Concrete Component
)角色:定义一个将要接收附加责任的类。- 装饰(
Decorator
)角色:持有一个构件(Component
)对象的实例,并实现一个与抽象构件接口一致的接口。- 具体装饰(
Concrete Decorator
)角色:负责给构件对象添加上附加的责任。此处我们有一个诉求:使用装饰者模式,使不同饮料主体搭配不同配料动态输出相应价格及信息。
二、装饰者模式使用
2.1 示例关系:
2.2 代码实现:
/* *
* 1. Component(被装饰对象的基类):茶类
*/
abstract class Tea {
public abstract String getDesc();
public abstract Double getPrice();
}
/* *
* 2. ConcreteComponent(具体被装饰对象):咖啡、奶茶继承茶类
*/
class Coffee extends Tea {
@Override
public String getDesc() {
return "咖啡";
}
@Override
public Double getPrice() {
return 15.0D;
}
}
class MilkyTea extends Tea {
@Override
public String getDesc() {
return "奶茶";
}
@Override
public Double getPrice() {
return 12.0D;
}
}
/* *
* 3. Decorator(装饰者类):配料装饰者
*/
class BatchingDecorator extends Tea {
/* *
* 继承并持有 被装饰对象的基类
*/
private final Tea tea;
public BatchingDecorator(Tea tea) {
this.tea = tea;
}
@Override
public String getDesc() {
return tea.getDesc();
}
@Override
public Double getPrice() {
return tea.getPrice();
}
}
/* *
* 4. ConcreteDecorator(具体装饰者):布丁和糖继承配料装饰者
*/
class Pudding extends BatchingDecorator {
public Pudding(Tea tea) {
super(tea);
}
@Override
public String getDesc() {
return super.getDesc() + " 加布丁";
}
@Override
public Double getPrice() {
return super.getPrice() + 2.0D;
}
}
class Sugar extends BatchingDecorator {
public Sugar(Tea tea) {
super(tea);
}
@Override
public String getDesc() {
return super.getDesc() + " 加糖";
}
@Override
public Double getPrice() {
return super.getPrice() + 1.0D;
}
}
public class Client {
public static void main(String[] args) {
Tea tea = new Coffee();
tea = new Sugar(tea);
System.out.println(tea.getDesc() + "售价为:" + tea.getPrice());
// 咖啡 加糖售价为:16.0
Tea tea1 = new MilkyTea();
tea1 = new Sugar(tea1);
tea1 = new Pudding(tea1);
System.out.println(tea1.getDesc() + "售价为:" + tea1.getPrice());
// 奶茶 加糖 加布丁售价为:15.0
}
}
三、装饰者模式总结
优点:
Decorator
模式与继承关系的目的都是要扩展对象的功能,但是Decorator
可以提供比继承更多的灵活性。- 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。
缺点:
- 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
- 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
适用场景:
- 需要扩展一个类的功能,或给一个类添加附加职责。
- 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
- 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
- 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
在JDK中的应用:
java.io.FileInputStream
四、结束语
“-------怕什么真理无穷,进一寸有一寸的欢喜。”
微信公众号搜索:饺子泡牛奶。