我应该如何向已存在的对象添加功能?


25

我有一个具有一定数量明确定义的功能的接口。比方说:

interface BakeryInterface {
  public function createCookies();
  public function createIceCream();
}

这对于大多数接口实现都很有效,但是在某些情况下,我需要添加一些新功能(例如,可能已添加到新方法中createBrownies())。这样做的显而易见/天真的方法是扩展接口:

interface BrownieBakeryInterface extends BakeryInterface {
  public function createBrownies();
}

但是有一个很大的缺点,就是我不能在不修改现有API的情况下添加新功能(例如,更改类以使用新接口)。

我正在考虑使用适配器在实例化后添加功能:

class BrownieAdapter {
  private brownieBakery;

  public function construct(BakeryInterface bakery) {
    this->brownieBakery = bakery;
  }

  public function createBrownies() {
    /* ... */
  }
}

这会让我感到类似:

bakery = new Bakery();
bakery = new BrownieBakery(bakery);
bakery->createBrownies();

这似乎是解决该问题的好方法,但是我想知道是否通过这样做唤醒了老神。适配器是要走的路吗?是否有更好的模式可以遵循?还是我真的应该只是硬着头皮,只是扩展原始界面?


Delphi具有帮助器类,就像将方法添加到现有类中而无需真正修改它们。例如,Delphi在其图形单元中定义了一个TBitmap类,您可以创建一个助手类,该类向TBitmap添加一个Flip函数。只要helper类在作用域内,就可以调用MyBitmap.Flip;。
比尔

Answers:


14

根据您的确切要求,语言和所需的抽象级别,任何“ 句柄主体”模式都可以适合描述。

纯粹的方法是Decorator模式,它可以完全满足您的需求,可以动态地向对象添加职责。如果您实际上是在建造面包店,那肯定是过大了,您应该选择Adapter。


这正是我所需要的:我意识到使用适配器可以解决依赖项注入问题,但是使用装饰器可以解决这个问题。

5

研究水平重用的概念,您可以在其中找到诸如Traits,仍处于试验阶段但已经过生产的面向方面编程以及有时讨厌的Mixins之类的东西

向类添加方法的直接方法还取决于编程语言。Ruby允许猴子修补,而Javascript 基于原型的继承实际上并不存在,您可以创建一个对象并复制并继续添加,例如:

var MyClass = {
    do : function(){...}
};

var MyNewClass = new MyClass;
MyClass.undo = function(){...};


var my_new_object = new MyNewClass;
my_new_object.do();
my_new_object.undo();

最后,您还可以通过反射来模拟水平重用或类/对象行为的运行时“修改”和“添加” 。


4

如果要求bakery实例必须动态更改其行为(取决于用户操作等),则应采用Decorator模式

如果bakery不能动态更改其行为,但是您不能修改Bakery class(外部API等),则应使用Adapter模式

如果bakery不能动态更改其行为,并且可以修改,Bakery class则应该扩展现有接口(如最初建议的那样)或引入一个新接口, BrownieInterfaceBakery实现两个接口BakeryInterfaceBrownieInterface
否则,您将无缘无故地在代码中添加不必要的复杂性(使用Decorator模式)!


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.