【问题标题】:Decorator Pattern - Adding functionality not defined in interface装饰器模式 - 添加接口中未定义的功能
【发布时间】:2018-07-30 13:58:29
【问题描述】:

对于这种模式的使用是否有任何硬性规定,或者它只是为了在不使用继承的情况下在方法调用中实现附加功能的一种方式?

我已经修改了以下示例,该示例取自 SO 帖子,以展示我正在考虑的内容。

 public interface Coffee {
     public double getCost();
     public String getIngredients();
 }
public class SimpleCoffee implements Coffee {
   @Override
   public double getCost() {
    return 1;
   }
   @Override
   public String getIngredients() {
    return "Coffee";
   }
}

 public class CoffeeDecorator implements Coffee {
   protected final Coffee decoratedCoffee;

   public CoffeeDecorator(Coffee c) {
    this.decoratedCoffee = c;
   }
   @Override
   public double getCost() { 
    //you can add  extra functionality here.
    return decoratedCoffee.getCost();
  }
   @Override
   public String getIngredients() {
    //you can add  extra functionality here.
    return decoratedCoffee.getIngredients();
   }

   public boolean methodNotDefinedInInterface() {
       //do something else
       return true;
   }
}

那么考虑到上面的例子,是否可行:

a) 只要你觉得合适就使用简单的咖啡,不要装饰它

b) 将 Coffee 接口中未定义的附加功能添加到装饰器对象,例如 methodNotDefinedInInterface()

有人也可以解释一下组合在哪里进入这种模式,因为SimpleCoffee 是可以独立存在的东西,但它似乎是实际“拥有”任何对象的装饰器。

尽管没有SimpleCoffee 类(或Coffee 的一些具体实现),装饰器没有任何用途,所以聚合似乎不是这里发生的事情。

【问题讨论】:

标签: java decorator


【解决方案1】:

description of the pattern 包含意图,它非常清楚该模式的用途:

装饰器模式可用于静态扩展(装饰)某个对象的功能,或者在某些情况下在运行时独立于同一类的其他实例,只要在设计时完成一些基础工作。

至于“硬性规则”——我一般认为模式中根本没有“硬性规则”。就像,如果你没有完全按照 GoF 的描述来实现它,就不会有“模式警察”来惩罚你。唯一的一点是,如果您遵循经典准则,其他开发人员在识别您的代码中的模式时遇到的问题会更少。

从我的角度来看,你的例子还不错。

SimpleCoffee 不是装饰器,所以那里没有组合。 CoffeeDecoratordecoratedCoffee 作为一个组件(在这里你有你的作文)

【讨论】:

  • 哈哈哈谢谢!你对“模式警察”的评论让我笑了,他们可能不是一个真正的单位,但每个组织都有几个自任命的成员,我敢肯定!好的答案,我从我提供的相当基本的例子中得到它仍然遵守经典指南?您发布的描述说“可以使用......”我想这足以说明它不必以这种方式完全使用。干杯!
  • @berimbolo 我现在在 Radiohead 的“Karma Police”旋律中播放“Pattern Police”。
【解决方案2】:

a) 只要你觉得合适就使用简单的咖啡,不要装饰它

是的,当然。

b) 添加未在 Coffee 中定义的附加功能 装饰器对象的接口,例如 方法NotDefinedInInterface()

您可以添加更多方法,就像向SimpleCoffee 类添加新方法一样,但请注意,您需要在装饰器类的某处使用这些额外的方法。


就我个人而言,当有人给你一个Coffee 的实例(即你没有实例化它)时,我发现这种模式很有用。如果您需要在运行时更改其行为,唯一的方法是将其包装在另一个 Coffee 类型的对象中。这是您可以将其放入装饰器类的时候。装饰器可以在提供一些新行为的同时公开一些原始行为。

【讨论】:

  • 好的,谢谢,也许我的用例毕竟不适合。我正在对一组难以理解的类进行一些重构,其中使用了多层抽象,使代码有点像噩梦。在这种情况下,定义了多种不同类型的请求,其中包含许多重复的方法和属性,我将其重构为一个基本请求,然后使用装饰器将功能添加到更具体的请求类型,而无需走更多抽象层的路径。 .
  • @berimbolo 如果不同的行为在编译时是固定的(确定的),那么您可以使用正常的继承(可能使用策略模式等)。当有人在运行时向您抛出一个对象时,装饰器非常有用,您需要更改或添加一个小功能,然后假装它是原始对象。
猜你喜欢
  • 2021-11-24
  • 1970-01-01
  • 1970-01-01
  • 2018-11-09
  • 2010-11-22
  • 1970-01-01
  • 2011-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多