为什么我们需要装饰器设计模式中的装饰器?[英] Why do we need the decorator in the decorator design pattern?

本文是小编为大家收集整理的关于为什么我们需要装饰器设计模式中的装饰器?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

假定我有一个名为A的课程,我想使用装饰器设计图案.如果我错了,请纠正我,但是要为此,我们需要创建一个装饰班,例如ADecorator,它将具有对A实例的参考,所有其他装饰师都会将其扩展到添加功能.

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

推荐答案

装饰器模式用于动态地添加功能(即在运行时).通常,当您编写课程时,对象将具有其功能.但是一个重要的一点是,对象的功能是以与对象客户端透明的方式扩展的,因为它实现了与原始对象相同的接口委托对装饰对象的责任.

在对象可能具有许多可选功能的情况下,装饰器图案在情况下起作用.没有装饰器图案,您将必须为每个对象选项配置创建一个不同的类.一个非常有用的示例来自O'Reilly的 Head First Design Design模式 .它使用一个听起来像星巴克的咖啡店示例.

因此,您拥有基本的咖啡,并具有类似成本的方法.

public double cost(){
     return 3.45;
}

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

public double cost(){
    return 3.80;
}

然后,客户可能想要摩卡咖啡的价格为0.5,并且他们可能想要摩卡咖啡,奶油或摩卡咖啡,而没有奶油.因此,您可以创建Coffeemochacream和Coffeemocha的课程.然后,客户想要双霜,因此您可以创建一个咖啡饼奶油……等等.请原谅使用的可怜的例子.有点晚了,我知道这很琐碎,但确实表达了重点.

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

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

您可以创建一个扩展项目的混凝土咖啡类:

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

然后,您创建了一个咖啡因,以扩展相同的接口并包含一个项目.

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

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

public class Mocha extends CoffeeDecorator{

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

}

请注意,只要它是一个物品,装饰器如何不关心它包装的类型?它使用项目对象的成本(),只是添加了自己的成本.

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

等等.

其他推荐答案

在某些语言中(例如Ruby或JavaScript),您可以在一个实例中添加新功能.我注意到您的问题被标记为Java,所以我想您在问为什么您不能在Java中这样做.原因是Java是静态键入的.一个实例只能拥有A类定义或继承的方法.因此,如果您想在运行时给一个实例一个未定义的方法,则必须在其他类中定义此新方法.

其他推荐答案

顺便说一句,如果您只是刚开始使用图案,则首先设计模式书是 emanmenal .它确实使这些概念简单地消化,并确保以一种非常容易理解的方式对比和比较类似的模式.

本文地址:https://www.itbaoku.cn/post/627631.html

问题描述

Presuming I have a class named A, and I want to use the decorator design pattern. Correct me if I'm wrong, but for that to work , we'll need to create a decorator class, say ADecorator, which will hold a reference to an A instance, and all the other decorators will extend this to add functionality.

I don't understand why do we have to create a decorator class, instead of using an A instance?

推荐答案

The decorator pattern is used to add capabilities to objects dynamically (that is, at run time). Normally the object will have its capabilities fixed when you write the class. But an important point is that the functionality of the object is extended in a way that is transparent to the client of the object because it implements the same interface as the original object delegates responsibility to the decorated object.

The decorator pattern works in scenarios where there are many optional functionality that an object may have. Without the decorator pattern you will have to create a different class for each object-option configuration. One example that is pretty useful comes from the Head First Design Patterns book by O'Reilly. It uses a coffee shop example that sounds just like StarBucks.

So you have the basic coffee with a method like cost.

public double cost(){
     return 3.45;
}

Then the customer can add cream which costs 0.35 so you now create a CoffeeCream class with the cost method:

public double cost(){
    return 3.80;
}

Then the customer may want Mocha which costs 0.5, and they may want Mocha with Cream or Mocha without Cream. So you create classes CoffeeMochaCream and CoffeeMocha. Then a customer wants double cream so you create a class CoffeeCreamCream… etc. What you end up with is class explosion. Please excuse the poor example used. It's a bit late and I know it's trivial but it does express the point.

Instead you can create an Item abstract class with an abstract cost method:

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

And you can create a concrete Coffee class that extends Item:

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

Then you create a CoffeeDecorator that extend the same interface and contain an Item.

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

Then you can create concrete decorators for each option:

public class Mocha extends CoffeeDecorator{

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

}

Notice how the decorator does not care what type of object it is wrapping just as long as it's an Item? It uses the cost() of the item object and simply adds its own cost.

public class Cream extends CoffeeDecorator{

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

}

Now it is possible for a large number of configurations with these few classes: e.g.

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

or

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

And so on.

其他推荐答案

In some languages (like Ruby or JavaScript) you could just add new functionality to an A instance. I notice that your question is tagged Java, so I assume that you are asking why you can't do this in Java. The reason is that Java is statically typed. An A instance can only ever have the methods that class A defines or inherits. Therefore, if you want at run time to give an A instance a method that A does not define, then this new method must be defined in a different class.

其他推荐答案

BTW, if you're just starting out on patterns, the Head First Design Patterns book is phenomenal. It really makes the concepts simple to digest, and makes sure to contrast and compare similar patterns in a way that is ridiculously easy to understand.