OOP:クラスベースのデザインがインターフェイスベースのデザインよりも優れている状況にはどのようなものがありますか?


9

JDOMのウェブサイトを読んでいました 。

JDOM APIがインターフェイスではなく具象クラスで定義されているのはなぜですか?

Jason Hunterは、JDOMのインターフェースベースのAPIに対する引数を要約しています。

インターフェースではすべてがファクトリーになり、要素を追加するだけでなく新しいドキュメントに「インポート」する必要があり、長期的なシリアル化などの機能は保証されず、リストは続きます。

実際にインターフェースから始めました。いくつかの同僚へのリリース前のレビュー中に、具体的なクラスを試すべきフィードバックを受け取りました。私たちはそうしました、そしてデザインはそれのためにはるかに優れていました。

私は初心者デザイナーです。私が今までについて聞いたことがすべてのアドバイスをさに対して助言具象クラスを使用した設計を使用しました。

特定の場所で適切なクラスを使用している場合があります。デザインで具象クラスを使用しても問題ない、一般的なクラスの問題はありますか?


あなたはこれを見てみたいかもしれません:javaworld.com/javaworld/jw-09-2001/jw-0921-interface.html
NoChance

:あなたはまた、「あなたの抽象化を制限」シリーズをチェックアウトすることができますayende.com/blog/153889/...
henginy

「私たちはそうしました、そしてデザインはそれのためにはるかに優れていました。」-どうだった?
CodeART、2012年

回答:


5
  • 継承は実装への依存関係を作成します。これは、保守性に関する大きな問題になる可能性があります。この当然の結果として、データ転送オブジェクト処理するときに、継承クラスと具象クラスを安全に使用できます。これには、定義上、ほとんど実装が含まれていません。この依存関係が必要な場合は、具象クラスの継承を使用することもできます。この状況では、階層の最上位にある一般的なメソッド(通常はユーティリティ関数)を含む抽象クラスを使用することをお勧めします。
  • 具体的なクラス階層を使用する場合は、リスコフ代入原則を適用することを忘れないでください。
  • クライアント用の具象クラス(つまり、使用されるクラスではなく使用されるクラス)を使用しても問題はありません。
  • 私見では、変更点があるまで具象クラスを使用できます。開放/閉鎖原則は、 カップリングを避けるためにインタフェースを使用することを教えてくれますが、について考えますゴナニードそれ原理ではないです、あなたが変更に実装で何かを必要とする瞬間まで、具体的なクラスを使用して検討するかもしれません。問題は、何かが初めて変更されたときに、クラスのすべてのクライアントを変更する必要があることです。何かを行うためのツールは1つしかありませんが、具象クラスIMOを使用できます。

[編集] JDOMのWebサイトはjava.io.Fileを例にしていますが、java.io.Fileインスタンスをシリアライズ可能であるかのように操作できるため、これは間違いなくインターフェースベースの設計です。この状況では、「作成者」だけが具体的なクラスを知っています。


浮かんでいる「値オブジェクト」には、2つの矛盾する定義があります。あなたのものはあまり一般的ではないようで、「データ転送オブジェクト」としても知られています。
Michael Borgwardt

@MichaelBorgwardt Thx私が「データ転送オブジェクト」だけを意味したのではないので、これを指摘してくれました:私は自分の回答を編集します
Matthias Jouan

1
LSPはサブタイプの関係、インターフェイスの実装、および継承にとって重要です。

2

JDOMサイトから:

ジェイソン(ハンター)は、2000年初頭にブレットマクラフリンとともにJDOMプロジェクトを設立しました。

つまり、Java 1.3が導入された頃のことです。Java開発に関しては、成熟度の点で何もありませんでした。最も経験豊富な開発者は、Javaを最高で4年しか使用していませんでした。広く使用されているIoCコンテナやHibernateはありませんでした。Apache Strutsはまだ始まったばかりです。

ジェイソンとブレットがちょうど間違っていたと言うことはすべてです。多くの人がまだ「理解」していません。彼らがC ++のバックグラウンドを持っているなら、まあ、C ++のインターフェースは必要ありません(まあ、C ++にはありましたが、実際には必要ありませんでした)。まあ、他の人があなたに指示することができる多くの正当な理由があります。

彼らは間違いなく間違っていた

インターフェイスで実行できることはすべてサブクラス化で実行できます

Javaでは、クラスの多重継承は許可されていませんが、複数のインターフェースの実装は許可されています。それは本当の違いを生むことができます。


2

まず、ソフトウェア開発では問題を解決する方法がいくつかあります。開発者があなたとは異なる手法を使用している場合でも、それが間違っていることを意味するわけではありません。

それらのケースの1つは、「インターフェース」対(ベース)「クラス」です。両方の手法で同じ目標を達成できる状況があります。

物事をより複雑にするために、インターフェイスのいくつかの使用法があります。

  • 1つは、「実装」なしで「契約」または「仕様」を設計することです。
  • その他は、既存のクラスまたはクラスの階層に機能を追加します
  • さまざまなオブジェクト、テクノロジー、例:Enterprise Beans、CORBA、COM、WebServices間の共有アクセスを可能にするために、以前のものを補完
  • 多重継承をエミュレートする

あなたの質問は最初の点に当てはまります。

単一のクラスだけでなく、クラス階層を開発する必要があり、いくつかのクラスが特定の機能を共有することを目的としている場合は、インターフェイスで実行できる場合でも、基本クラスから開始することができます。

そして、他のシナリオのためにインターフェースを残します。

良い例は、ウィジェット(コントロール)ライブラリです。

他のプログラミング言語を見て、PHP、Delphi(Object Pascal)、C#などのインターフェイスとクラスをどのように使用するかを検討することをお勧めします。

乾杯。


0

通常、パラメーターとして渡される、または返されるすべてのもののインターフェースが必要です。基本的に、依存関係からクラスを分離することができます。

そのため、クラスを探している場合、通常は例外を回避することはできません。私はJava開発者ではありませんが、他の同様の言語では、例外用に定義されたインターフェースを見たことはないと思います。


0

APIのデザインルールは本当に特定のものです。日常のコードをどのように設計すればよいかという点で、このFAQから結論を出す必要があるかどうかはわかりません。

通常のコードでは、バニラ継承IMOよりもインターフェイスまたは抽象クラスの継承を頻繁に使用することは事実です。

そのルールをよく理解するには、派生クラスとそのスーパークラスの観点からではなく、別のオブジェクトへの依存関係を持つオブジェクトの観点から自分を配置する必要があります。一連のさまざまなクラス全体を依存関係として受け入れ、実装の詳細ではなくコントラクトに依存できるため、ほとんどの場合、具体的な実装よりも抽象化に依存する方が優れています。

これの最初の使用は、多くの場合、ユニットテストで行われます。完全に分離してクラスをユニットテストしたい場合は、本番環境で使用される実際の実装とは異なる依存関係の偽の実装に対して行います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.