List<Apple>
オブジェクトがあり、それぞれのリンゴに色があるとしましょう。
Apple オブジェクトのリストを入力として構築される別のオブジェクトを実装します。このオブジェクトに「緑のリンゴの数を教えて」などの機能を実装すると、そのオブジェクトの内部表現を知らなくても呼び出すことができます。
あなたはこの男を何と呼びますか?基本的な OO のようですが、わかりやすい名前を考えるのに苦労しています。
List<Apple>
オブジェクトがあり、それぞれのリンゴに色があるとしましょう。
Apple オブジェクトのリストを入力として構築される別のオブジェクトを実装します。このオブジェクトに「緑のリンゴの数を教えて」などの機能を実装すると、そのオブジェクトの内部表現を知らなくても呼び出すことができます。
あなたはこの男を何と呼びますか?基本的な OO のようですが、わかりやすい名前を考えるのに苦労しています。
オッズについて話しているので、 (リストはコレクションを継承します)List<Apple>
についても話しているということです。Collection<Apple>
「コレクション」を強調したい場合は、「コレクション」と名付けます。りんごは伝統的にブッシェル単位で販売されていましたが、測定には関心がないので、より一般的な (サイズに依存しない) 用語「バスケット」を使用します。
public class Basket {
private int greenCount;
public void addApple(Apple apple) {
if (apple.isGreen()) {
greenCount++;
}
}
public int getGreenAppleCount() {
return greenCount;
}
}
これは、バスケット内の青リンゴを数える責任を適切に捉えています。
一方、ユーティリティは、タスクの責任を特定の型にバインドされたオブジェクトから切り離しているように見えます。たとえば、架空の を見てみましょうAppleCounterUtil
。
public class AppleCounterUtil {
public int getCount(Collection<Apple> apples, AppleCondition condition) {
int count = 0;
for (Apple apple : apples) {
if (condition.isSatisfied(apple)) {
count++;
}
}
}
}
そして今、実際にはカウントを維持するのではなく、おそらく異なるリンゴのリストから必要になるたびにカウントを再計算する素晴らしいユーティリティがあります。
重要な点は、後者の例は概念的なオブジェクトがないため、オブジェクト指向ではないということです。オブジェクトが存在しないと述べる根拠は、ユーティリティを含むクラスに状態がないためです。オブジェクトは、データと密接に関連するコードのコレクションです。コードしかない場合、オブジェクトではなく名前空間関数があるという合理的な議論を行うことができます。
違いをもう一度確認するために、2 つのコード スニペットを比較してみましょう。最初の「バスケット」アプローチの使用:
...
int greenOnes = basket.getGreenAppleCount();
basket.addApple(new GreenApple());
greenOnes = basket.getGreenAppleCount();
...
非常に扱いにくくなりますが、私たちはオブジェクト指向Basket Listener
であるため、インターフェースを簡単に追加できます。Basket
public class Basket {
public void addListener(BasketListner listener) {
...
}
public void addApple(Apple apple) {
...
for (BasketListnener listner : listeners) {
listener.appleAdded(this);
}
}
}
... some other class ... implements BasketListener {
int greenOnes = 0;
...
public void appleAdded(Basket basket) {
greenOnes = basket.getGreenAppleCount();
}
}
ユーティリティ指向のテクニックを使用しながら
...
int greenOnes = AppleCounterUtil.getCount(apples, new GreenCountCondition());
apples.addApple(new GreenApple());
greenOnes = AppleCounterUtil.getCount(apples, new GreenCountCondition());
...
より多くの機能を追加しようとするまで、表面上は似ています。「アップル リスト リスナー」を追加しようとするとAppleCounterUtil
、カウントを維持する責任がなく、リッスンできないことがすぐにわかります。また、カウントを維持する責任を負う「りんごのリスト」もありません。また、一般化されたリストは、通常、リッスンするための間違ったインターフェイスを提示します。
残念ながら、ユーティリティ指向になると、通常、ユーティリティ メソッドを追加することで問題を解決しようとします。これは最終的に、特定の関心事 (りんごのグループを管理する人) が多くのユーティリティに分散される可能性があることを意味する可能性があります。各ユーティリティは、オンデマンドで計算できる「機能」のみを提供します。
オンデマンド計算機能は、場合によっては、他の計算オンデマンド機能に依存するようになる可能性があり、2 つの間に機能的な結合が得られます (コードが直接結合されていなくても)。この効果的な結合は、特定の一連のユーティリティを順番に呼び出さなかったり、必要なユーティリティ呼び出しを省略したりすると、コードが壊れることを意味します。極端なケースは、オブジェクトが最終的にデータ構造になる程度まで動作を失ったり、オブジェクトに通常関連付けられる動作を欠いたりする場合です。これは、「貧血オブジェクト」として知られるオブジェクト指向設計のアンチパターンです。