描述
- 在不改变原有类对象结构的情况下,动态给该对象增加一些额外的功能
角色
- 抽象目标对象
- 目标实现对象
- 抽象装饰:
- 具体装饰:
实现
public class Test {
public static void main(String[] args) {
BlackTea blackTea = new BlackTea();
System.out.println(blackTea.getName() +blackTea.cost());
Pearl pearl = new Pearl(blackTea);
// 类似套娃,子类装饰父类,父类装饰父类的父类
System.out.println(pearl.getName() +pearl.cost());
Pearl pearl2 = new Pearl(pearl);
System.out.println(pearl2.getName() +pearl2.cost());
Coconut coconut = new Coconut(pearl2);
System.out.println(coconut.getName() +coconut.cost());
}
}
// 奶茶店,抽象目标对象
abstract class MilkTeaShop {
private double price;
private String name;
MilkTeaShop(double price, String name) {
this.price = price;
this.name = name;
}
public String getName() {
return name;
}
public double getPrice() {
return price;
}
// 计算
abstract double cost();
}
// 红茶 具体对象
class BlackTea extends MilkTeaShop {
BlackTea() {
super(9.5, "红茶");
}
@Override
double cost() {
return getPrice();
}
}
// 配料 抽象装饰类 要装饰哪个对象。继承它。然后拿自己去装饰它
abstract class MixedIngredients extends MilkTeaShop {
private MilkTeaShop milkTeaShop;
MixedIngredients(MilkTeaShop milkTeaShop, double price, String name) {
super(price, name);
this.milkTeaShop = milkTeaShop;
}
public MilkTeaShop getMilkTeaShop() {
return milkTeaShop;
}
}
// 珍珠 具体装饰者
class Pearl extends MixedIngredients {
Pearl(MilkTeaShop milkTeaShop) {
super(milkTeaShop, 2.0, "珍珠");
}
@Override
double cost() {
return super.getPrice() + getMilkTeaShop().cost();
}
@Override
public String getName() {
return super.getName() + getMilkTeaShop().getName();
}
}
// 椰果 具体装饰者
class Coconut extends MixedIngredients {
Coconut(MilkTeaShop milkTeaShop) {
super(milkTeaShop, 1.5, "椰果");
}
@Override
double cost() {
return super.getPrice() + getMilkTeaShop().cost();
}
@Override
public String getName() {
return super.getName() + getMilkTeaShop().getName();
}
}
// 绿茶 具体目标
class GreenTea extends MilkTeaShop {
GreenTea() {
super(10.0, "绿茶");
}
@Override
double cost() {
return getPrice();
}
}
优点
- 在继承的基础上进行扩展,灵活,良好的扩展性。
- 使用更加方便,可动态的扩展功能, 遵循开闭原则。
- 装饰者和目标对象,可以独立扩展,不会相互耦合。
使用场景
- 当不能采用或不好采用 继承 的方式对系统进行扩充时。
- 如:final修饰的类。
- 如:当有大量子类时,要对每一个子类进行扩展,子类数据呈现爆炸性增长。
- 在不影响其它子类的情况下,以动态,透明的方式对当前对象扩展。
JDK中的使用
- IO流的 Buffered系列
- 如BufferedWriter
public class Test {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("");
BufferedWriter bw = new BufferedWriter(fw);
bw.write("abc");
bw.close();
}
}
// BufferedWriter对Writer进行了装饰者模式的增强(增加了缓冲区)(继承,聚合Writer)
public class BufferedWriter extends Writer {
private Writer out;
public BufferedWriter(Writer out) {
this(out, defaultCharBufferSize);
}
静态代理和装饰者模式的区别
相同点
- 都要实现目标对象相同的业务接口
- 都声明了目标对象
- 都可以在不修改目标对象的前提下增强目标方法
不同点: - 目的不同,装饰者是为了增强;而代理对象是为了隐藏
- 构建不同,装饰者是由外界传递进来,聚合,增强;静态代理是内部创建,组合隐藏对象。