あなたの混乱はあなたの構成の理解から来ます。別のオブジェクトが所有するオブジェクトは、所有するオブジェクトの存続期間に依存します。これは所有するオブジェクトを所有するクラス内に作成しなければならないという意味ではありません。
クラスにオブジェクトを作成した場合、このクラスは作成されたクラスと緊密に結合されています。他のクラスを作成するクラスを変更せずに実装を交換することはできません。
例:あなたは、クラスのサーバーを使用するクラスのクライアントを、持っている上の写真で
。これはコンポジションであり、クライアントにはタイプServerという属性があります。
あなたは、クライアントクラスの内部クラスサーバーのインスタンスを作成した場合、それは次のようになります。
public class Client {
private Server server;
public Client(){
this.server = new Server();
}
}
は今、あなたはサーバーの実装を交換したいと言うことができます。 Clientクラスの実装を変更する必要があるのは、それを交換する唯一の方法は別のクラス(AnotherServerと呼ばれることもある)のインスタンスを作成することだからです。
public class Client {
private AnotherServer anotherServer;
public Client(){
this.anotherServer = new AnotherServer();
}
}
これは、クライアントクラスがクラスサーバーに強く依存していることを示しています。
サーバの使用されている実装を簡単に変更し、クライアントの動作を変更するには、抽象クラス(抽象クラスまたはインタフェース)からクライアントを構成する方がよいでしょう。そうすることで、具象クラスのみを作成できるので、所有するクラスで必要なオブジェクトを作成することはできません。クラスの作成とは、コンストラクターを呼び出し、作成されたクラスに依存することを意味します。
コンポジションを達成するためのよりよい方法(クライアントはサーバーから構成されます)は、セッターメソッドまたはコンストラクターを使用して注入することです。このように、インターフェイスの背後に実装クラスを隠すことができます。
例:私たちはサーバーの具体的な実装についての知識からクライアントを保護する二絵で
。それはサーバーインターフェイスに依存します。この依存関係は、クライアントがインターフェイスを定義するため、劇的なものではありません。彼は、Serverインターフェイスの必要な機能について決定します。サーバのインタフェースがクライアントに属していることを示すために、それを「ClientServer」と呼ぶ。
クライアントを作成するには、クラス外のClientServerインターフェイス用の具体的なクラスを作成し、コンストラクタまたはセッタメソッドを通じて注入する必要があります。このよう
...
FirstServer first = new FirstServer();
Client client = new Client(first);
client.setServer(new SecondServer());
...
あなたは簡単にも、実行時に、クライアントで使用されるサーバーの実装を交換することができます。
このメカニズムは、依存性反転の原理(DIP)と呼ばれます。しかし、なぜ? Clientクラスは引き続きサーバーインターフェイスに依存しています。インタフェースが変更された場合、クライアントも変更する必要があります。はい、これは正しいです。しかし、クライアントは、彼がそのインタフェースで必要とする機能を決定します。したがって、通常、クライアントは変更が必要だと言ったときにインタフェースが変更されます。クライアントが変更されるため、インタフェースが変更されます。
具体的なサーバー "FirstServer"と "SecondServer"はClientServerインターフェイスを実装しているため、そのインターフェイスにも依存しています。継承はコンポジションよりも依存性が強いため、具体的なサーバークラスはClientクラスよりもインターフェイスに依存しています。
これは、依存関係が逆転している理由です。具体的なサーバークラスは、現在、 "Client-ClientServer" -conglomerateに依存しています。
あなたの質問に対する答えは次のとおりです。別のクラスにクラスを作成するときにDIPに到達することはできません。しかし、このインターフェースを継承する具象クラスを注入するインターフェースを定義することによって、DIPに到達することができます。
ここに矛盾はありません。オブジェクトは、コンストラクタで渡されるいくつかの他のオブジェクトで構成されています。何ですか? –
私はクラス間の依存関係とオブジェクト間の依存関係を混在させていると思います。もちろん、合成オブジェクトはそのコンポーネントに依存します。しかし、抽象化(インターフェイス)を使用している場合は、クラス間に依存関係があるということではありません。 –
@FrankPuffer依存性注入を使用して合成を使用できますか? – justsomedev