1

インターフェイス IBuilding と IDwelling があり、両方を実装するクラス House があるとします。建物と住居をカプセル化します。

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

IBuilding と IDwelling がそれぞれ 15 個のメソッドを定義している場合、House クラスに 30 個のメソッドを記述して、ドアまたは窓のメソッドに転送するだけでよいのでしょうか?

それは非常に退屈に思えます。これは本当に事ですか?多くのリソースは、そうです、それがあなたがすることであることを示していますが、それらはすべて、私が想像するほど困難にならないように、非常に単純な例を使用しています。

または、私が気付いていない、よりスマートな構成方法はありますか?

4

2 に答える 2

1

こんなに面倒じゃないですか?いいえ、もっとスマートな方法はありますか? はい。

あなたがコンポジションを使用する理由として、私が考えることができる 3 つの理由があります。

  1. オブジェクト間の「has a」関係を確立します。
  2. ある種のラッパー クラス (デコレータ/プロキシ) を作成します。
  3. あなたの言語に当てはまる場合は、単一継承の制約をバイパスします。

3 つのうち、ケース #2のみ、ラッパー クラスからのすべての呼び出しをラップされたクラスに転送する必要があります。それでも、呼び出しを転送するためだけに、内部クラスのすべてのメソッドに対して外部クラスにメソッドを作成する必要がないように、いわゆる「動的」プロキシを作成できる言語がいくつかあります。たとえば、Java ではDynamic Proxy Class、PHP ではマジック__call()メソッドと呼ばれます。

もう1つのことは、あなたが質問で説明したような状況は実際には非常にまれであることです.

アップデート

ここでの主な問題は、ラッパー クラスにラップされたクラスのインターフェイスを実装させたい場合に PHP を使用している間、__call()メソッドは実際には役に立たないということです。インターフェイスにメソッドがほとんどない場合、それらを実装するのは難しくありませんが、15 個ある場合はどうなるでしょうか? この問題は構成の問題ではなく、大きなインターフェースの問題だと私は信じています。このような問題を回避するには、 Interface Segregation Principleに従う必要があります。ただし、汎用 API を作成している場合、原則に従うのが難しい場合があります。この場合、メソッド呼び出しを 1 対 1 でマッピングする以外にできることはありません。ごめん。

于 2012-12-20T08:24:14.750 に答える
0

極端な例のように思えますが、そうです、コンポジションとは水平方向に委譲することであり、ほとんどの場合、その委譲を明示的にプログラムする必要があります。プログラミングしている言語によっては、Traitsが「グルー コード」を書かずに水平方向の構成を実現するための優れたメカニズムであることがわかる場合があります。論文Traits: Composable Units of Behaviorは、垂直方向の再利用の問題と、なぜ特性のようなアプローチが代替手段であるかを説明している、良い読み物であると思うかもしれません。

HTH

于 2012-12-19T12:49:19.643 に答える