2011-12-22 18 views
7

静的メソッドを保持せずにシングルトンクラスを作成する必要があります。静的メソッドを使用せずにクラスシングルトンを作成する

どうすればいいですか?

+0

コンストラクタを1回だけ呼び出す。 –

+0

静的変数を使用しますか? – dasblinkenlight

+2

@M Platvoet - これはシングルトンではありません。コンストラクタをもう一度呼び出すことができるからです。 –

答えて

19

つのインスタンスで

enum Singleton { 
    INSTANCE; 

    private Field field = VALUE; 
    public Value method(Arg arg) { /* some code */ } 
} 

// You can use 
Value v = Singleton.INSTANCE.method(arg); 

EDIT列挙型を作成します。Java Enum Tutorialがenumにフィールドやメソッドを追加する方法を示しますが。


はところで:あなたがシングルトンを使用することができたときに多くの場合、あなたは本当にユーティリティクラスとして1が同じことを行います必要はありません。さらに短いバージョンはただのものです

enum Utility {; 
    private static Field field = VALUE; 
    public static Value method(Arg arg) { /* some code */ } 
} 

// You can use 
Value v = Utility.method(arg); 

ここでシングルトンは、インターフェイスを実装するときに便利です。これは、依存関係注入を使用するときのテストに特に便利です。 (ユニットテストでシングルトンまたはユーティリティクラス置換を使用する弱点の1つ)

interface TimeService { 
    public long currentTimeMS(); 
} 

// used when running the program in production. 
enum VanillaTimeService implements TimeService { 
    INSTANCE; 
    public long currentTimeMS() { return System.currentTimeMS(); } 
} 

// used in testing. 
class FixedTimeService implements TimeService { 
    private long currentTimeMS = 0; 
    public void currentTimeMS(long currentTimeMS) { this.currentTimeMS = currentTimeMS; } 
    public long currentTimeMS() { return currentTimeMS; } 
} 

あなたが見ることができるようにあなたのコードはどこにでもTimeServiceを使用している場合、あなたは、すなわちあなたのタイムスタンプがテストを実行するたびに同じになり、外部からの時間を制御することができVanillaTimeService.INSTANCEまたはnew FixedTimeService()のいずれかを注入することができます。

要するに、インタフェースを実装するためにシングルトンを必要としない場合は、ユーティリティクラスが必要です。

+0

@Pater素早い返信ありがとう –

+0

私はそれを取得しない...あなたのシングルトンにはどのメソッドも呼び出すことはできません –

+0

@remi bourgarel java enumは単なるクラスです。他のクラスと同じように、変数、メソッド、およびコンストラクタをSingleton列挙型(INSTANCEの宣言の後)に追加するだけで、INSTANCEにはそれらがあります。 – josefx

1

"Effective Java"第2版のJoshua Bloch列挙レシピに従います。これがシングルトンを作成する最良の方法です。

なぜこのようになるのか分かりません。シングルトンは信用できないデザインパターンですか? GoFは今日、島からそれを投票するだろう。

1

IoCコンテナの1つ(例:Google Guice)を使用し、クラスをシングルトンとして使用することができます(必要に応じて熱心なまたは怠け者です)。インスタンス化はIoCフレームワークによって制御されるので、簡単で柔軟性があります。たとえば、後でシングルトンにしないようにする場合は、コードを変更する必要はありません。

+0

インタビューの質問の文脈では、IoCコンテナのような巨大なフレームワークを導入することで、そうした小さな問題を解決することは良い考えではありません。 –

+0

なぜですか? IoCは現在かなり普通のことです。インタビュアーがそれを知っていて、IoCフレームワークを可能な解決策の1つとして使用することを提案すればプラスです。 – Artem

+0

はい、IoCは最近よく知られています。これまでのところ、すべてのプロジェクトで使用されているわけではありません。インタビュアーが以前にIoCフレームワークに関心を示さなかったならば、_I_はその質問が言語そのものについての知識をテストしたいと思っていると仮定します。単純なことが単純な方法ではなく、いくつかの重いフレームワークを含む複雑な方法でしか行えないことがわかっている場合は、通常の問題解決スキルが同じように機能すると推測できます。
ベストプラクティス:両方のソリューションを表示する。 –

8
public class Singleton { 
    public static final Singleton instance = new Singleton(); 
    private Singleton() {} 
    public void foo() {} 
} 

、この工場からあなたのシングルトンオブジェクトを取得し、オブジェクトファクトリを使用し

Singleton.instance.foo(); 
+1

完全性のために:非引数のプライベートなコンストラクタを追加してください。 –

+0

素晴らしい!ありがとうございます。 (私の定期的な間違い:) – andrey

0

を使用しています。

ObjectFactory factory; 
.... 
MySingletonObject obj = factory.getInstance(MySingletonObject.class); 

もちろん、これを達成するための多くのフレームワークがあります。 スプリングフレームワークは一般的な選択です。

+0

静的メソッドを使用しているIsntファクトリ?それは彼が望んでいないものです。 – Eduard

0

コンストラクタの中から、クラスのインスタンスが既に存在するかどうかを調べる必要があります。だから、静的変数やクラスにあなたのシングルトンインスタンスへの参照を格納する必要があります。次に、シングルトンのコンストラクタで、シングルトンクラスの既存のインスタンスが存在するかどうかを常にチェックします。はいの場合は、私はそれを作成し、参照を設定しない場合は何もしません。

2

別のアプローチは、要求に応じて初期化を提供singleton holder idiomである:それは促進するため、このようなスタンドアロンシングルトンが可能な場合は避けるべきであること

public class Something { 
     private Something() { 
     } 

     private static class LazyHolder { 
       public static final Something INSTANCE = new Something(); 
     } 

     public Something getInstance() { 
       return LazyHolder.INSTANCE; 
     } 
} 

(例変性、getInstanceメソッドが静的でない製)

注単体テストのコードにつながり、単一のクラスローダーコンテキストに依存して、いくつかの可能性のある欠点を示しています。

関連する問題