English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Javaのデザインパターンの単例パターンの詳細な解説

この記事では、Javaのデザインパターンのシングルトンパターンの具体的なコードを共有し、参考にしてください。具体的な内容は以下の通りです

概念:

シングルトンパターン:クラスには一つのインスタンスしかありません。

クラスには一つのインスタンスしかなく、グローバルなアクセスポイントを提供します。

このパターンを使用する理由:

  ウェブサイトを閲覧しているとき、一部のウェブサイトは「現在のオンライン人数」を表示します。この機能を実現する方法は、ログインした各IPをメモリ、ファイル、またはデータベースに保存することで、IPが増えるごとに「+1。一般的には、メソッドを使用して実現します。例えば、add()メソッドです。+1の機能を使用する場合、例えば「update」文を使用して、データベースに保存されているデータを取得して、+1データベースのデータを更新して、保存します;ページに表示される際には、別のメソッドを通じてデータベースのデータを取得します。しかし、複数のユーザーが同時にログインする場合、各ユーザーが新しいオブジェクトを作成し、それを「オブジェクト.メソッド名」を通じてadd()メソッドを実行し、データをデータベースに保存すると、実際のユーザーデータが正確にデータベースに記録されない問題が発生します。したがって、このカウンターをグローバルオブジェクトとして設計することで(誰もがこのオブジェクトを使用し、新しいオブジェクトを作成するのではなく)、誰もが同じデータを使用し、このような問題を避けることができます。これがシンプルモデルの適用の一つです。 

同様に、他のシーンでも似たような状況に直面し、似たような考え方が使用されます。例えば:

   1外部リソース:各コンピュータにはいくつかのプリンタがありますが、プリンタスプールルーは二つの印刷作業が同時にプリンタに送信されるのを避けるために、一つだけあります。内部リソース:ほとんどのソフトウェアにはシステム設定を保存するための属性ファイルがあります。このようなシステムには、属性ファイルを管理するオブジェクトが一つ(または複数)あるべきです。
   2Windowsのタスクマネージャ(タスク管理器)も非常に典型的なシンプルモデルです(非常に馴染みがあるでしょう)。思えば、二つのWindowsタスクマネージャを開けることができますか?信じられないなら自分で試してみてくださいね~
   3Windowsのリサイクルバイン(リサイクルバスケット)も典型的なシンプルモデルのアプリケーションです。システムの全体運行中にリサイクルバスケットは唯一のインスタンスを維持しています。
   4ウェブサイトのカウンターも一般的にはシンプルモデルで実装されています。他の方法でシンクロナイズするのが難しいからです。
   5アプリケーションのログアプリケーションも一般的にはシンプルモデルで実装されています。これは共有のログファイルが常に開かれているため、一つのインスタンスしか操作できないためです。
   6ウェブアプリケーションの設定オブジェクトの読み取りも一般的にはシンプルモデルが適用されます。これは設定ファイルが共有リソースだからです。
   7データベース接続プールの設計も一般的にはシンプルモデルが採用されています。なぜならデータベース接続はデータベースのリソースだからです。データベースソフトウェアシステムではデータベース接続プールを使用することで、データベース接続をオープンまたはクローズする際に発生する効率の低下を節約することができます。この効率の低下は非常に高価です。シンプルモデルを使用してこれを維持することで、この低下を大幅に減少させることができます。
   8マルチスレッドのスレッドプールの設計も一般的にはシンプルモデルが採用されています。これはスレッドプールがプール内のスレッドを制御しやすいためです。
   9オペレーティングシステムのファイルシステムは、大きなシンプルモデルの具体的な実装例でもあります。一つのオペレーティングシステムには一つのファイルシステムしかありません。
   10、HttpApplication も単例の典型的な適用です。ASP.Net (IIS) の全体のリクエストライフサイクルに詳しい人なら、HttpApplication も単例パターンであることを知っているでしょう。すべての HttpModule は同じ HttpApplication インスタンスを共有します。 

簡単にまとめると、単例パターンの一般的な適用シナリオは以下の通りです:

    1、頻繁にインスタンス化して破棄する必要があるオブジェクト。

    2、オブジェクトを作成する際に時間がかかるまたはリソースが多く、しかし頻繁に使用されるオブジェクト。

      3、状態を持つツールクラスのオブジェクト。

    4、データベースやファイルに頻繁にアクセスするオブジェクト。

    5、リソースを共有する場合、リソース操作時のパフォーマンスや損耗などの問題を避けることができます。例えば、上記のログファイル、アプリケーション設定など。

    6、リソースを制御する場合、リソース間の相互通信が便利です。例えば、スレッドプールなど。

特徴:

1、単例クラスはただ一つのインスタンスを持つ必要があります;

2、単例クラスは自分自身のユニークなインスタンスを自分自身で作成する必要があります;

3、単例クラスはすべての他のオブジェクトにこのインスタンスを提供する必要があります;

単例パターンの要素: 

   1私有構築メソッド
   2私有静的リファレンスが自分のインスタンスを指す
   3公共静的メソッドが自分のインスタンスを返す 

単例パターンの実現方法は以下の3つです:

1hungryman :単例インスタンスはクラスのロード時に構築され、急速に初期化されます。(事前ロード法)

/**
* hungryman (推奨)
*
*/
public class Test {
    private Test() {
    }
    public static Test instance = new Test();
    public Test getInstance() {
        return instance;
    }
}

利点 

    1線程安全
    2クラスのロードの際にすでに静的オブジェクトが作成され、呼び出し時の反応速度が速い。

欠点 

    リソース効率が低く、 getInstance() が決して実行されない可能性がありますが、このクラスの他の静的メソッドを実行したり、このクラス(class.forName)をロードすると、このインスタンスが初期化されます。

2lazyman :単例インスタンスは最初に使用される際に構築され、遅延初期化されます。

class Test {
    private Test() {
    }
    public static Test instance = null;
    public static Test getInstance() {
        if (instance == null) {
       //複数のスレッドが instance が null であると判断した場合、 new 操作を実行する際に複数のスレッドが重複する可能性があります。
            instance = new Singleton2()
        }
        return instance;
    }
}

利点 

    hungryman 構造体が無駄に事例を作成するのを避け、リソースの利用効率が高く、 getInstance() を実行しないとインスタンスは作成されません。また、このクラスの他の静的メソッドを実行できます。

欠点 

    lazyman 構造体は単一スレッドでは問題ありませんが、複数のスレッドが同時にアクセスすると、複数のインスタンスが同時に作成される可能性があり、これらのインスタンスは同じオブジェクトではありません。後で作成されたインスタンスは最初に作成されたインスタンスをオーバーライドしますが、異なるオブジェクトを取得する可能性があります。この問題を解決する方法は、ロックシンクロナイズを使用することです。最初のロード時は速くありませんが、多线程での使用では不必要なシンクロナイズのコストが大きいです。

3.双重检测

class Test {
    private Test() {
    }
    public static Test instance = null;
    public static Test getInstance() {
        if (instance == null) {
            synchronized (Test.class) {
                if (instance == null) {
                    instance = new Test();
                }
            }
        }
        return instance;
    }
}

利点 

    リソースの利用効率が高く、getInstance()を実行しないとインスタンス化されませんが、他の静的メソッドを実行できます

欠点 

    初回のロード時には反応が遅い、Javaメモリモデルの一部の理由により、時々失敗します

4.静的内部クラス

class Test {
    private Test() {
    }
    private static class SingletonHelp {
        static Test instance = new Test();
    }
    public static Test getInstance() {
        return SingletonHelp.instance;
    }
}

利点 

    リソースの利用効率が高く、getInstance()を実行しないとインスタンス化されませんが、他の静的メソッドを実行できます

欠点 

    初回のロード時には反応が遅い

まとめ: 

    一般的には「ハンガー式」が採用されますが、リソースが非常に重要である場合は「静的内部クラス」を使用することをお勧めします。また、「ラディアン式」や「双重检测」は使用しないことをお勧めします。

 これで本文のすべての内容が終わりました。皆様の学習に役立てば幸いですし、もっと「呐喊教程」をサポートしていただけると嬉しいです。

声明:本文の内容はインターネットから取得しており、著作権者に帰属します。インターネットユーザーが自発的に貢献し、自己でアップロードしたものであり、本サイトは所有権を持ちません。また、人工編集は行われておらず、関連する法的責任を負いません。著作権侵害を疑う内容がある場合は、以下のメールアドレスにご連絡ください:notice#oldtoolbag.com(メールを送信する際には、#を@に置き換えてください。報告を行い、関連する証拠を提供してください。一旦確認がとりついたら、本サイトは即座に侵害疑いのコンテンツを削除します。)

おすすめ