为什么我们需要装饰器设计模式中的装饰器?

2022-09-03 17:57:06

假设我有一个名为 的类,并且我想使用装饰器设计模式。如果我错了,请纠正我,但要做到这一点,我们需要创建一个装饰器类,比如说,它将保存对实例的引用,所有其他装饰器将扩展它以添加功能。AADecoratorA

我不明白为什么我们必须创建一个装饰器类,而不是使用一个实例?A


答案 1

装饰器模式用于动态(即在运行时)向对象添加功能。通常,在编写类时,对象的功能将固定。但重要的一点是,对象的功能以对对象客户端透明的方式进行扩展,因为它实现了与原始对象将责任委派给装饰对象相同的接口。

装饰器模式适用于对象可能具有许多可选功能的情况。如果没有装饰器模式,则必须为每个对象选项配置创建不同的类。一个非常有用的例子来自O'Reilly的Head First Design Patterns一书。它使用了一个听起来像星巴克的咖啡店的例子。

所以你有基本的咖啡和像成本这样的方法。

public double cost(){
     return 3.45;
}

然后,客户可以添加成本为 0.35 的奶油,因此您现在使用成本方法创建一个 CoffeeCream 类:

public double cost(){
    return 3.80;
}

然后,客户可能想要成本为0.5的摩卡,他们可能想要带奶油的摩卡或没有奶油的摩卡。因此,您可以创建类CoffeeMochaCream和CoffeeMocha。然后一个客户想要双层奶油,所以你创造了一个类咖啡奶油奶油...等。你最终得到的是阶级爆炸。请原谅使用这个可怜的例子。这有点晚了,我知道这是微不足道的,但它确实表达了这一点。

相反,您可以使用抽象成本方法创建 Item 抽象类:

public abstract class Item{
    public abstract double cost();
}

您可以创建一个扩展 Item 的具体 Coffee 类:

public class Coffee extends Item{
    public double cost(){
       return 3.45;
    }
}

然后,创建一个 CoffeeDecorator,它扩展了相同的界面并包含一个 Item。

public abstract class CoffeeDecorator extends Item{
     private Item item;
     ...
}

然后,您可以为每个选项创建混凝土装饰器:

public class Mocha extends CoffeeDecorator{

   public double cost(){
     return item.cost() + 0.5;
   }

}

请注意,装饰者并不关心它包装的是什么类型的对象,只要它是一个 Item?它使用 item 对象的 cost(),并简单地添加自己的成本。

public class Cream extends CoffeeDecorator{

   public double cost(){
     return item.cost() + 0.35;
   }

}

现在,可以使用以下几个类进行大量配置:例如

 Item drink = new Cream(new Mocha(new Coffee))); //Mocha with cream

 Item drink = new Cream(new Mocha(new Cream(new Coffee))));//Mocha with double cream

等等。


答案 2

顺便说一句,如果你刚刚开始研究模式,那么Head First Design Patterns书是非凡的。它确实使概念易于消化,并确保以一种非常容易理解的方式对比和比较类似的模式。


推荐