ここ数か月の間に、私は次のテクニック/パターンを何度か見つけました。しかし、私は特定の名前を見つけることができないようで、そのすべての利点と欠点について100%確信しているわけではありません。
パターンは次のようになります。
Javaインターフェース内では、通常どおり一連の共通メソッドが定義されていますが、内部クラスを使用すると、デフォルトのインスタンスがインターフェースからリークされます。
public interface Vehicle {
public void accelerate();
public void decelerate();
public static class Default {
public static Vehicle getInstance() {
return new Car(); // or use Spring to retrieve an instance
}
}
}
私にとって、最大の利点は、開発者がインターフェースについて知るだけでよく、その実装について知る必要がないという事実にあるようです。すぐにインスタンスを作成したい場合に備えて。
Vehicle someVehicle = Vehicle.Default.getInstance();
someVehicle.accelerate();
さらに、構成に応じてインスタンスを動的に提供するために、Springとともにこの手法が使用されることを確認しました。この点で、これもモジュール化に役立つように見えます。
それにもかかわらず、インターフェースをその実装の1つに結合しているため、これがインターフェースの誤用であるという印象を揺るがすことはできません。 (依存関係の逆転の原理など)このテクニックの呼び方、およびその長所と短所を誰かに教えてもらえますか?
更新:
しばらく検討した後、再確認したところ、次のシングルトンバージョンのパターンがはるかに頻繁に使用されていました。このバージョンでは、パブリック静的インスタンスは、(フィールドがfinalであるため)一度だけ初期化されるインターフェースを通じて公開されます。さらに、インスタンスはほとんどの場合、Springまたはインターフェースを実装から切り離す汎用ファクトリーを使用して取得されます。
public interface Vehicle {
public void accelerate();
public void decelerate();
public static class Default {
public static final Vehicle INSTANCE = getInstance();
private static Vehicle getInstance() {
return new Car(); // or use Spring/factory here
}
}
}
// Which allows to retrieve a singleton instance using...
Vehicle someVehicle = Vehicle.Default.INSTANCE;
一言で言えば:これはカスタムのシングルトン/ファクトリパターンであり、基本的にはそのインターフェースを介してインスタンスまたはシングルトンを公開できるようです。不利な点に関しては、以下の回答とコメントでいくつか挙げられています。これまでのところ、利点はその便利さにあるようです。
_Default.getInstance
_はIMHOです factory method の非常に具体的な形式であり、 singleton pattern から取られた命名規則と混同されます(ただし、後者)。現在の形式では、これは「 単一責任の原則 」の違反です。これは、インターフェース(クラスAPIの宣言の目的をすでに果たしている)が、デフォルトのインスタンスを提供するという追加の責任を負うためです。別のVehicleFactory
クラスに配置することをお勧めします。
この構成要素によって引き起こされる主な問題は、Vehicle
とCar
の間に循環依存関係を引き起こすことです。たとえば、現在の形式では、Vehicle
を1つのライブラリに配置し、Car
を別のライブラリに配置することはできません。別のファクトリクラスを使用して_Default.getInstance
_メソッドを配置すると、その問題が解決します。シングルトンに関連する混乱を防ぐために、そのメソッドに別の名前を付けることも良い考えです。結果は次のようになります
VehicleFactory.createDefaultInstance()
これは Null Object パターンのように見えます。
しかし、それはCar
クラスの実装方法に大きく依存します。 「ニュートラル」な方法で実装されている場合、それは間違いなくNullオブジェクトです。つまり、インターフェイスですべてのnullチェックを削除し、null
が発生するたびにこのクラスのインスタンスを配置できる場合でも、コードは正しく機能する必要があります。
また、このパターンであれば、インターフェイス自体とnullオブジェクトの実装との間の密結合を作成する問題はありません。 nullオブジェクトは、上記のインターフェイスが使用されているすべての場所に存在できるためです。