1

Java クラスから別のオブジェクトの機能 (メソッド) を使用するための適切な OO 設計について議論していますが、両方のオブジェクトは可能な限り分離されたままです。

たとえば、クラスのある時点で、ロジックを実装するために、ヘルパー クラスなどの別のオブジェクトに属するメソッドを呼び出す必要があります。このヘルパー クラスは、元のクラスに関連している必要はまったくありません。クラスに表示され、クラスで使用できる特定のメソッドが含まれているだけです。

ロジックが実装された後は、ヘルパー メソッド (またはヘルパー オブジェクト) は必要ありません。

明らかに、メソッドを使用するには、このヘルパー オブジェクトへの参照が必要です。しかし、カプセル化を強制するには、元のクラスでインスタンス変数を宣言して、このヘルパー オブジェクトを参照するべきではありませんか? その理屈は正しいですか?また、ヘルパー クラスは、それを使用する可能性のあるクライアント クラスを認識しません。

この場合、ローカル変数の方が適切でしょうか? その機能を利用するメソッドでヘルパー オブジェクトを宣言してインスタンス化しますか? このようなヘルパー オブジェクトを宣言してインスタンス化するのに最適な場所は、元のクラスのどこですか?

高レベルの例があるかどうか、またはオブジェクト指向の記事でもう少し詳しく説明されているかどうか疑問に思っていました。上記のカプセル化に焦点を当てた入力またはヒントをいただければ幸いです。

4

6 に答える 6

2

しかし、カプセル化を強制するには、元のクラスでインスタンス変数を宣言して、このヘルパー オブジェクトを参照するべきではありませんか? その理屈は正しいですか?

いいえ、インスタンス変数を宣言することは、カプセル化を破ることとは何の関係もありません。

関連する考慮事項は次のとおりです。

  • 依存関係: デフォルトでは、使用するユーティリティ クラスに依存し、依存しません。必要に応じて、さまざまな手法 (インターフェース、戦略パターン、依存性注入など) を使用して、その依存性を逆転または削減できます。しかし、単純なケースでは、それに応じておそらく問題ありません。
  • オブジェクトの有効期間: オブジェクトの場合、使用する時点で存在している必要があります。存在するということは、意味的に何かを意味する (つまり、プログラムの他の部分の動作を変更する) か、パフォーマンスに影響を与える可能性があります (作成するのにコストがかかるか、不要なときにぶらぶらしておくと大量のメモリを占有します)。したがって、その性質と目標の両方に適合する、その寿命を処理する方法が必要です。

基本的な選択肢は次のとおりです。

  • 1 つ以上の関数のローカル非共有変数- 必要に応じて作成され、関数が終了するとすぐに消えます。おそらくデフォルトの選択です。それ以外はすべて最適化または特殊なケースです。
  • コンストラクターで作成された共有インスタンス変数- 一度だけ作成されますが、オブジェクト自体がガベージ コレクション/破棄されるまで続きます。
  • 初回使用時に作成される共有インスタンス変数- 上記と同様ですが、複雑さを犠牲にして作成を遅らせます。
  • 外部静的関数- オブジェクトがないため、寿命の問題はありません。内部状態がなく、単純なインターフェイスを持たないものに適しています。そうしないと、暗黙的なオブジェクトの有効期間が関数へのコメントによってのみ管理されることになります ( strcpyなどの C ライブラリ関数のように)。

高度な選択肢:

  • 外部シングルトン- オブジェクトはそれ自身のライフタイムを管理し、利用できることを保証します。いくつかの場合は問題なく動作しますが、使いすぎる可能性が非常に高くなります。
  • 依存性注入- 他の誰か (通常は構成ファイルによって管理されるフレームワーク) がカプセル化を破り、必要なオブジェクトを挿入します。

これを行う他のすべての方法 (たとえば、オブジェクトをコンストラクターまたはメソッド引数に追加する) は、システムに余分な依存関係を追加するため、少なくとも上記の基本的な選択が適切でない場合を除き、実行しないでください。

于 2009-08-29T12:04:31.563 に答える
1

正しい答えは、ヘルパー クラス (H) とその上で使用するメソッド (M)、および元のオブジェクト クラス (C) の間の関係の性質によって異なります。あなたはいくつかの重要な点に言及しました:

  • 必要なロジックを に入れたくありませんC
  • 代わりに配置しましHた。
  • H.M()によって 1 回だけ使用されCます。
  • Hクライアントに依存しません。
  • 「明らかに、そのメソッドを使用するには、このヘルパー オブジェクトへの参照が必要です」と言うので、インスタンス メソッドである のHインスタンスのみを操作できると仮定します。M()

いくつかの解決策があります。

  • M静的メソッドとして優れていないかどうかを評価します。静的メソッドを見たことがあるなら、これは非常に説得力のある使い方です。Hが状態を維持することについては何も言及していません。

  • 戦略パターンを使用します。H.M()何かを行う特定の方法を表す場合H、 はパターンの Strategy オブジェクトですC。同様のメソッドを持つ他の のHようなクラスがある場合M()、これらは選択できるさまざまな戦略です。

于 2009-08-29T11:12:44.770 に答える
0

私は、Javaクラスから別のオブジェクトの機能(メソッド)を使用するための適切なオブジェクト指向設計について議論していますが、両方のオブジェクトは可能な限り分離されたままです。

あなたはこれにあまりにも多くの努力を払っています。デカップリングは、接続がまったくないことを意味するものではありません。ヘルパーオブジェクトを一度使用する場合は、それを使用するブロックのコードにパラメーターとして渡すか、クラスにファクトリからインスタンスを取得させます。

しかし、ある時点で、それへの参照が必要になります。明らかに、メンバーインスタンスがそれを参照することは望ましくありません(メモリリークの可能性があります)。つまり、ヘルパーへの参照を取得する、ある種のファクトリまたはインスタンスマネージャを呼び出すことになります。

しかし、これで行き過ぎないでください。目標は、デカップリングゲームをプレイしたり、人為的で冗長なクラス階層に物事を適合させたりすることではなく、解決策を得ることです。後者は、OOの概念の最悪の使用法です。

于 2010-06-30T02:55:07.637 に答える
0

では、これはシナリオですか?これらは質問ですか?

Class MyClass {
   private SomeState myState;

   public voic oneMethod() {
         // Q1 : what type is **ahelper** ?
         // Q2 : where do we declare it ?
         // Q3 : where do we initialise it?
         aHelper.doSomeWork();

         // update your state depending upon the results
   }
}

Q1. aHelper を Interface として宣言する必要があると思います

 HelperInterface aHelper;

次に、特定の実装に結合されません。

Q2. 1 つの場所でのみ使用する場合は、その関数で宣言し、それ以外の場合はメンバー変数として宣言します。どちらを行ってもカップリングは増加しません。

 HelperInterface aHelper = ? what here?
 aHelper.soSomeWork();

Q3. コンストラクタまたはファクトリを使用した遅延ゲッターで初期化します。

public MyClass(HelperInterface injectedHelper) {
    aHelper = injectedHelper;
}

これにより、テストが非常に簡単になり、テストでモック ヘルパー クラスをインジェクトでき​​ます。

または、遅延初期化子を使用できます。ヘルパーがメソッド内のローカル変数である場合、これは非常に便利です。ここでも、好みに応じてファクトリを注入するか静的にすることができます。

private getHelper() {
    if (aHelper == null ){ make the helper, perhaps using a factory }

    return aHelper     
}
于 2009-08-29T21:22:50.603 に答える
0

静的メソッドはテストが難しく、別のメソッドで呼び出される静的メソッドはモックが困難です。テストの観点から考えると、良い設計を行うのは簡単だと思います。メソッドが非静的メンバーである場合、そのメソッドをテストしなくても、そのメソッドを呼び出すコードを簡単に単体テストできます。私と一緒にいますか?メソッド m がネットワークを使用して何かを行うとしましょう。そのメソッドが静的である場合、メソッド m を使用するコードをテストするたびに、ネットワークで処理が行われます。そして、ネットワーク関連が失敗した場合、テストは失敗しますが、テストしたいコードは失敗します。分かりますか?静的でない場合は、メソッドでオブジェクトをモックして、常に「OK」を返すようにすることができます。

そうは言っても、ヘルパーをパラメーターとしてメソッド、またはヘルパーインターフェイスとして送信します。そうすれば、あなたのクラスはヘルパーを作成する方法、またはどのタイプでさえも完全に忘れてしまいます。知らぬが仏。クラスはそれを使用する方法、美しいものだけを知っています。:)

于 2009-08-29T11:44:46.797 に答える
-1

静的メソッドを使用したり、シングルトンヘルパー オブジェクトを使用したりしませんか?

于 2009-08-29T11:07:41.253 に答える