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

标签 java design-patterns decorator

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

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

最佳答案

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

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

因此,您可以通过类似成本的方法获得基本的咖啡。

public double cost(){
     return 3.45;
}

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

public double cost(){
    return 3.80;
}

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

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

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

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

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

然后您创建一个 CoffeeDecorator,它扩展相同的接口(interface)并包含一个 Item。

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

然后你可以为每个选项创建具体的装饰器:

public class Mocha extends CoffeeDecorator{

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

}

请注意装饰器如何不关心它包装的是什么类型的对象,只要它是一个 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

等等。

关于java - 为什么我们需要装饰器设计模式中的装饰器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/273943/

相关文章:

java - jersey2 单元测试,HttpServletRequest 为空

java - 重构具有许多子类的抽象 Java 类

zend-framework - 如何在一个 Zend_Form 中连续放置 2 个按钮

java - Java 库中有 Decorator 类吗?

c# - 在结构图中为 DecorateAllWith() 方法定义过滤器 3

java - 通过jdbc填充数据库

java - Facebook android sdk 需要 java 1.7 才能工作吗?

java - 对 map 进行排序时出现问题

javascript - 单例比 TypeScript 中的模块有优势吗?

design-patterns - 我应该如何重构这个设计