web-dev-qa-db-ja.com

スタティックなしのシングルトンパターン

static(Javaの意味で、基本的に静的メソッドはインスタンスではなくクラス自体で呼び出されます)はTrue OOPではないと聞きました。しかし、シングルトンパターンはこのような言語で実装されます。FooGetterクラスを作成し、そのインスタンスでgetFoo()メソッドを呼び出すことを考えましたが、FooGetterは静的変数なしでFooのインスタンスをどのように格納しますか?

1
vikarjramun

次のようなシングルトンパターンの実装:

public final class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

依存性注入で置き換えることができます。静的メソッドmainでオブジェクトを1回作成し、それを必要とするすべてのものに渡します。

public static void main(){
    Date applicationStart = new Date();

    Uptime uptime = new Uptime(applicationStart);
    Performance performance = new Performance(applicationStart);

    //...
}

ここで、両方ともアプリケーションの開始を知る必要があり、2回作成された日付を表示したくない2つのオブジェクトは、どちらも同じ単一のオブジェクトへの参照が与えられます。構築を恐れずに防ぐのではなく、責任を持って参照を迂回することにより、すべての要件が満たされます。シングルトンのユーザーは、それを見つける方法を知る必要がないので、このアプローチははるかに高い柔軟性を可能にします。

このアプローチの欠点は、遅延初期化をサポートしないことです。

ただし、これはオブジェクトの構築にコストがかかる場合にのみ必要です。多くの設計では、インスタンス変数の検証と保存以外の作業をコンストラクタに禁止することで、問題を回避しています。一般的に、どちらも遅延初期化を正当化するのに十分な費用はかかりません。オブジェクトのサイズは、遅延初期化の理由にもなります。良いデザインは大きなオブジェクトを避ける傾向があります。リソースを初期化し、オブジェクトの作成でその可用性をモデル化することも、遅延初期化を使用する理由となる場合があります。オブジェクトのライフタイムセマンティクスにより、どれだけの意味が言語に依存する可能性があります。

遅延初期化では、いずれの場合もシングルトンパターンは必要ありません。呼び出されたときに構築するオブジェクトもキャッシュする単一の抽象ファクトリオブジェクトと組み合わせたDIは、クライアントを構築コードにハードコーディングすることなく、遅延初期化要件も満たします。

シングルトンパターンは、優れたデザインにはそもそもない問題を解決するため、ほとんど避けられます。しかし、必要が生じた場合でも、今までどおりに機能します。オブジェクト指向かどうか。

4
candied_orange

staticがまったくないバージョン。安全な並行性。

public enum Singleton {
    INSTANCE;

    public final AtomicLong counter;

    Singleton() {
        counter = new AtomicLong(System.currentMillis());
    }

    /**
     * For unit testing.
     * @param value.
     */
    void setCounter(long value) {
        counter.set(value);
    }
}

並行性セーフ(列挙型で保証)、および最終クラス。

静的はそれ自体悪いことではありません。列挙型は静的です。シングルトンのスコープは静的です。スタティックはグローバル変数であり、メモリリークの原因となる可能性があり、テストが困難で、起動時のオーバーヘッドが増加します。

0
Joop Eggen