装饰者模式
定义
在不改变原有对象的基础之上,将功能附加到对象上。提供了比继承更有弹性的替代方案(扩展原有对象功能)
为什么要使用装饰者模式
如下图:我们的纯豆浆,可以搭配红糖,变成红糖豆浆,也可以搭配红豆变成红豆豆浆,同时也可以红糖配红豆一起组成红糖红豆豆浆,那如果我们每次有一个新的配料加入,我们就写一个新的类,将会导致我们的类无限多,类爆炸了,这个时候装饰者模式起作用了。
装饰者模式的结构
- 抽象组件(Component):给出一个抽象接口,以规范准备接收附加责任的对象(本文例子中为Drink 饮品对象)
- 被装饰者(ConcreteComponent):抽象组件(Component)的具体实现,也就是我们要装饰的具体对象(本文例子中为Soya豆浆对象)
- 装饰者(Decorator)组件:持有抽象组件(Component)的实例引用,该类的职责就是为了装饰具体组件对象定义的基类(本文例子中为Decorator 装饰器对象)
- 具体装饰(ConcreteDecorator):负责给构建对象装饰附加功能(本文中例子,就是红豆装饰豆浆)
具体代码
抽象组件(Component) Drink 饮品
package com.bowen;
public interface Drink {
//抽象组件
public String desc();
public double money();
}
被装饰者(ConcreteComponent) Soya 豆浆
package com.bowen;
public class Soya implements Drink {
//被装饰者
@Override
public String desc() {
return "纯豆浆";
}
@Override
public double money() {
return 5;
}
}
装饰者(Decorator)组件 Decorator
package com.bowen;
public abstract class Decorator implements Drink{
//装饰器
//1.抽象类
//2.实现抽像组件接口
//3.持有抽象接口引用
//定义私有的饮品接口
private Drink drink;
public Decorator(Drink drink){
this.drink = drink;
}
@Override
public String desc() {
return this.drink.desc();
}
@Override
public double money() {
return this.drink.money();
}
}
具体装饰(ConcreteDecorator) 这里是红豆
package com.bowen;
public class RedBean extends Decorator {
public RedBean(Drink drink){
super(drink);
}
@Override
public String desc() {
return super.desc() + "+红豆";
}
@Override
public double money() {
return super.money() + 4.2;
}
}
测试代码
package com.bowen;
public class Test {
public static void main(String[] args) {
Drink soya = new Soya();//新建豆浆
Drink redbean = new RedBean(soya); //加入红豆,生产红豆豆浆
System.out.println(redbean.desc());
System.out.println(redbean.money());
}
}
结果:
纯豆浆+红豆
9.2
优缺点
- 优点
- 提供比继承更好的灵活性,装饰是动态的,运行时可以修改,继承是静态的,编译期间已确定好。
- 通过使用不同的装饰类及他们的排列组合,可以创造出许多不同行为的组合。
- 缺点
- 容易产生许多小对象,大量的小对象占用内存
- 组合方式过多不好管理,容易出错