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

查看:108
本文介绍了为什么我们需要装饰设计师的装饰师?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个名为 A 的类,我想使用装饰器设计模式。纠正我,如果我错了,但为了工作,我们将需要创建一个装饰类,说 ADecorator ,它将持有一个 A 实例,所有其他装饰器将扩展它以添加功能。



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

解决方案

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



装饰器模式在一个对象可能具有许多可选功能的情况下工作。没有装饰器模式,您将不得不为每个对象选项配置创建一个不同的类。一个非常有用的例子来自于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。然后一个客户想要双重奶油,所以你创建一个类CoffeeCreamCream ...等等你最终得到的是类爆炸。请原谅可怜的例子。它有点迟了,我知道它的微不足道,但它确实表达了这一点。



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

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

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

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

然后,您创建一个CoffeeDecorator,扩展相同的界面和包含一个项目。

  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;
}

}

现在有可能这些几个类别的配置数量:
例如

 商品饮料=新奶油(新的摩卡咖啡) ); // Mocha with cream 

 商品饮料=新奶油(新的摩卡(新的奶油(新咖啡)))); //摩卡与双奶油

等等。


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 th ecustomer can add cream which cost 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 cost 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 etc. What you end up with is class explosion. Please excuse the poor example used. Its a bit late and I know its trivial but it does express the point.

Instead you can create an Item abstarct 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 its 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.

这篇关于为什么我们需要装饰设计师的装饰师?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆