疑問に思っていました...空白の値オブジェクトをインスタンス化するためのベストプラクティスとは何ですか? (Java)
例えば。値オブジェクトクラスFoo
があり、空白の場合があります。
このようなメソッドを作成することは、クリーンなソリューションでしょうか? (そしておそらく「空白の」インターフェースか何かを追加します)。
interface Blankable {
public Foo blankInstance();
public boolean isBlank();
}
class Foo implements Blankable {
public Foo blankInstance();
public boolean isBlank();
}
Foo foo = something();
if (foo.isBlank()) // Tell the user
それとも、このようなもっとシンプルなものが良いでしょうか?
class Foo {
public static Foo BLANK = /* Some constructor */;
}
Foo foo = something();
if (foo == Foo.BLANK) // Tell the user
私は最初の例に傾いていますが、それが広く受け入れられている手法であるかどうかはまだわかりません。
この状況では回避策のように思えるので、Guava Optional <T>クラスの使用には少し抵抗があります(ただし、まだオープンです)。
Option<T>
などのソリューションは、それほど悪い考えではありません。実際、Haskellでは Maybe としてうまく導入されています(ただし、このソリューションが初めて使用されたかどうかはわかりません)。 たぶんモナドはHaskellプログラムで一般的です。以来、他の言語も同じシステムを採用しています。たとえば、Scalaには Option タイプがあります。
Guavaに依存したくない場合は、Java 8を使用して オプション クラスを導入できます。
ただし、Option/Maybe /…タイプは機能的な環境でより関連性があります。なぜなら、通常は、要素が実際に存在する場合は要素から動作/プロパティを取得し、それ以外の場合は何も取得しないかデフォルトの動作/プロパティを取得するためです。 。したがって、Optionsの一般的な使用法は次のとおりです。
Option[A]
を取得するために、Option[B]
に関数A-> Bを適用します。代わりに、抽象クラスMyClassと2つの具象サブクラスがある Null Object Pattern を使用できます。 MyRealClassおよびMyNullClassMyClassのインスタンスを操作しますが、MyRealClassのインスタンスを生成します(要素は実際に存在します)またはMyNullClass(要素が存在しない場合)。 MyNullClassには、デフォルトの動作/プロパティが含まれています。 nullオブジェクトがステートレスである場合(これは一般的なケースです)、それらをキャッシュするか、シングルトンにすることさえできます。
このパターンは[Fowler]で説明されています。
[ファウラー]マーティンファウラー、ケントベック リファクタリング:既存のコードのデザインの改善
値オブジェクトの要点は、同等性はアイデンティティに基づいていないということです。 2つの異なる空白のオブジェクトを作成することもできます。実際、すべての空白オブジェクトが同じオブジェクトか異なるオブジェクトかは、実装の詳細である必要があります。これらの理由から、2番目のアプローチは適切ではありません。 Java 8 APIを見ると、次のプロパティを持つ「値ベースのクラス」という概念があります。
ドキュメントはさらに追加します:
プログラムが値ベースのクラスの等しい値への2つの参照を区別しようとすると、参照の等価性を介して直接的に、または同期、IDハッシュ、シリアル化、またはその他のIDセンシティブメカニズムへのアピールを介して間接的に、プログラムが予期しない結果を生成する可能性があります。値ベースのクラスのインスタンスでこのようなID依存操作を使用すると、予測できない影響が生じる可能性があるため、使用を避けてください。
Javaで==
演算子を無効にする方法はないため、警告を表示するのが最善です。
したがって、最初のアプローチは正しいです。ただし、foo1.equals(foo2)
の場合、foo1.isBlank()
は常にtrue
でなければならず、foo1 != foo2
であってもfoo2.isBlank()
である必要があります。