设计模式 -- 装饰器模式

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

含义: 在不改变原有对象的基础上添加新的功能,与继承相比能够更加灵活地扩展对象的功能。

下面是具体的实现方式,拿 coffee 和 tea 中添加 milk 举例,分别被装饰成 latte 和 milky tea

创建一个接口

1
2
3
csharp复制代码public interface Drink{
   void getName();
}

创建实现接口的实体类

1
2
3
4
5
6
7
8
9
10
11
12
13
typescript复制代码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 的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码public interface DrinkDecorator extends Drink{
   
   private Drink drink;
   
   public DrinkDecorator(Drink  drink){
       this.drink = drink;
  }
   
   @Override
   public void getName(){
       drink.getName();
  }
}

创建具体的装饰

1
2
3
4
5
6
7
8
9
10
11
12
13
scala复制代码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 对象

1
2
3
4
5
6
7
8
9
10
11
12
csharp复制代码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();
  }
}

上面代码可以看出装饰器模式包含四个角色,抽象接口,具体事物,抽象装饰,具体装饰;但是并不是所有的装饰器模式都要有这四个角色。当只有一个具体事物时,可以让抽象装饰直接继承具体事务;当只有一个具体装饰时,可以让抽象装饰和具体装饰进行合并。

什么时候使用这一模式呢?

  • 采用继承的方式会产生大量的子类
  • 类不可以被继承
  • 动态的添加和删除对象的功能

装饰器模式的主要优点

  • 在不改变原有对象的情况下,可以动态的给一个对象添加功能,能够做到即插即用
  • 装饰器模式遵守设计模式原则的开闭原则

但是装饰器模式同样会增加许多的子类,过度的依赖装饰器模式也会增加程序的复杂性。

与代理模式的区别

装饰器模式的关注点在于给对象动态添加⽅法,⽽动态代理更注重对象的访问控制。动态代理通常会在代理类中创建被代理对象的实例,⽽装饰器模式会将装饰者作为构造⽅法的参数。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%