「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」
含义: 在不改变原有对象的基础上添加新的功能,与继承相比能够更加灵活地扩展对象的功能。
下面是具体的实现方式,拿 coffee 和 tea 中添加 milk 举例,分别被装饰成 latte 和 milky tea
创建一个接口
public interface Drink{
void getName();
}
创建实现接口的实体类
public class Coffee implements Drink{
@Override
public void getName(){
System.out.println("Drink: Coffee");
}
}
public class Tea implements Drink{
@Override
public void getName(){
System.out.println("Drink: Tea");
}
}
创建装饰 Drink 的接口
public interface DrinkDecorator extends Drink{
private Drink drink;
public DrinkDecorator(Drink drink){
this.drink = drink;
}
@Override
public void getName(){
drink.getName();
}
}
创建具体的装饰
public class MilkDecorator extends DrinkDecorator{
public MilkDecorator(Drink drink) {
super(drink);
}
public void getName() {
super.getName();
setMilk();
}
public void setMilk() {
System.out.println("setMilk");
}
}
使用 MilkDecorator 来装饰 Drink 对象
public class DecoratorDemo {
public static void main(String[] args) {
System.out.println("drink latte");
Drink latte = new MilkDecorator(new Coffee());
latte.getName();
System.out.println("drink milky tea");
Drink milkyTea = new MilkDecorator(new Tea());
milkyTea.getName();
}
}
上面代码可以看出装饰器模式包含四个角色,抽象接口,具体事物,抽象装饰,具体装饰;但是并不是所有的装饰器模式都要有这四个角色。当只有一个具体事物时,可以让抽象装饰直接继承具体事务;当只有一个具体装饰时,可以让抽象装饰和具体装饰进行合并。
什么时候使用这一模式呢?
- 采用继承的方式会产生大量的子类
- 类不可以被继承
- 动态的添加和删除对象的功能
装饰器模式的主要优点
- 在不改变原有对象的情况下,可以动态的给一个对象添加功能,能够做到即插即用
- 装饰器模式遵守设计模式原则的开闭原则
但是装饰器模式同样会增加许多的子类,过度的依赖装饰器模式也会增加程序的复杂性。
与代理模式的区别
装饰器模式的关注点在于给对象动态添加⽅法,⽽动态代理更注重对象的访问控制。动态代理通常会在代理类中创建被代理对象的实例,⽽装饰器模式会将装饰者作为构造⽅法的参数。