1

假设您有接口 IBuilding 和 IDwelling,以及实现这两者的类 House。它封装了一座建筑和一座住宅:

class House implements IBuilding, IDwelling 
{
  private IBuilding building;
  private IDwelling dwelling;
}

如果 IBuilding 和 IDwelling 各自定义了 15 个方法,那么在 House 类中写 30 个方法只是转发到门或窗的方法真的很正常吗?

这看起来非常非常乏味。这真的是一回事吗?很多资源表明,是的,这就是你要做的,但他们都使用了超级简单的例子,这并不像我想象的那样令人生畏。

还是有一些我不知道的更聪明的作曲方法?

4

2 回答 2

1

有必要这么乏味吗?没有。有什么更聪明的方法吗?是的。

我能想到你为什么会使用这个组合的三个原因:

  1. 在对象之间建立“具有”关系;
  2. 创建某种包装类(装饰器/代理);
  3. 绕过单一继承约束,如果它适用于您的语言。

在这三种情况中,只有第 2 种情况可能要求您将每个调用从您的包装类转发到被包装类。即便如此,有些语言可能允许您创建所谓的“动态”代理,这样您就不必为内部类中的每个方法在外部类中创建一个方法来转发调用。例如,在 Java 中它被称为Dynamic Proxy Class,在 PHP 中它是魔术__call()方法。

另一件事是,您在您的问题中描述的情况在实践中非常罕见。

更新

这里的主要问题是,在使用 PHP 时,如果我们希望包装类实现被包装类的接口,那么__call()方法实际上并不能真正帮助我们。如果接口的方法很少,实现起来也不难,但如果有15个呢?这个问题,我相信不是组合的问题,而是大接口的问题。为避免此类问题,您需要遵循接口隔离原则。但是,有时,如果您正在编写通用 API,则很难遵循该原则。如果是这种情况,那么除了方法调用的一对一映射之外,您无能为力。对不起。

于 2012-12-20T08:24:14.750 回答
0

虽然这似乎是一个极端的例子,但是,是的,组合是关于横向委托,并且大多数时候你必须明确地对委托进行编程。根据您正在编程的语言,您可能会发现Traits是一种无需编写“胶水代码”即可实现水平组合的良好机制。您可能会发现论文Traits: Composable Units of Behavior是一本不错的读物,它解释了垂直重用的问题以及为什么像特征这样的方法是一种替代方法。

高温高压

于 2012-12-19T12:49:19.643 回答