logo

シングルトン方式の設計パターン

シングルトン パターンは、おそらく最も広く使用されているデザイン パターンです。シンプルなパターンなので、理解しやすく、使いやすいです。場合によっては、必要とされないシナリオで過剰に使用されることがあります。このような場合、それを使用することによるメリットよりもデメリットの方が大きくなります。このため、シングルトン パターンは、 アンチパターンまたはパターンシングルトン

シングルトンメソッド設計パターン



シングルトン メソッド設計パターンの重要なトピック

1. シングルトン方式デザインパターンとは何ですか?

シングルトン法またはシングルトン設計パターンは、最も単純な設計パターンの 1 つです。これにより、クラスにはインスタンスが 1 つだけ存在することが保証され、そのインスタンスへのグローバル アクセス ポイントが提供されます。

2. シングルトン メソッド デザイン パターンをいつ使用するか?

次の場合には、シングルトン方式のデザイン パターンを使用します。



  • クラスのインスタンスは 1 つだけ存在する必要があり、クライアントは既知のアクセス ポイントからアクセスできる必要があります。
  • 唯一のインスタンスがサブクラス化によって拡張可能であり、クライアントが変更せずに拡張されたインスタンスを使用できる必要がある場合
  • シングルトン クラスは、ロギング、ドライバー オブジェクト、キャッシュ、スレッド プール、データベース接続に使用されます。

3. シングルトンの初期化タイプ

シングルトン クラスは 2 つのメソッドでインスタンス化できます。

  • 早期初期化: このメソッドでは、クラスが使用されるかどうかに関係なく初期化されます。この方法の主な利点はその単純さです。クラスのロード時にクラスを開始します。この欠点は、クラスが使用されているかどうかに関係なく、常に初期化されることです。
  • 遅延初期化: このメソッドでは、必要な場合にのみクラスが初期化されます。不要なときにクラスをインスタンス化する手間を省くことができます。一般に、シングルトン クラスを作成する場合は、遅延初期化が使用されます。

4. シングルトンメソッド設計パターンの主要コンポーネント:

シングルトン方式設計パターンの主要構成要素(1)

4.1.静的メンバー:

シングルトン パターンまたはパターン シングルトンは、クラス内の静的メンバーを使用します。この静的メンバーにより、メモリが 1 回だけ割り当てられるようになり、Singleton クラスの単一インスタンスが保持されます。



ジャワ
// Static member to hold the single instance private static Singleton instance;>

4.2.プライベートコンストラクター:

シングルトン パターンまたはパターン シングルトンにはプライベート コンストラクターが組み込まれており、外部からシングルトン クラスのインスタンスを作成しようとする試みに対するバリケードとして機能します。これにより、クラスがそのインスタンス化プロセスを制御できるようになります。

ジャワ
// Private constructor to // prevent external instantiation class Singleton {  // Making the constructor as Private  private Singleton()  {  // Initialization code here  } }>

4.3.静的ファクトリーメソッド:

シングルトン パターンの重要な側面は、静的ファクトリ メソッドの存在です。このメソッドはゲートウェイとして機能し、シングルトン オブジェクトへのグローバル アクセス ポイントを提供します。誰かがインスタンスを要求すると、このメソッドは新しいインスタンスを作成するか (存在しない場合)、既存のインスタンスを呼び出し元に返します。

bash if ステートメント
ジャワ
// Static factory method for global access public static Singleton getInstance() {  // Check if an instance exists  if (instance == null) {  // If no instance exists, create one  instance = new Singleton();  }  // Return the existing instance  return instance; }>

5. シングルトン方式デザインパターンの実装

シングルトン デザイン パターンまたはパターン シングルトンの実装は、次のクラス図で説明されます。

スクリーンショット-2023-12-07-174635

シングルトン方式デザインパターンの実装

シングルトン設計パターンの実装は非常に単純で、単一のクラスで構成されます。シングルトン インスタンスが一意であることを保証するには、すべてのシングルトン コンストラクターをプライベートにする必要があります。コードに示すように、グローバル アクセスは、単一のインスタンスにグローバルにアクセスできる静的メソッドを通じて行われます。

ジャワ
/*package whatever //do not write package name here */ import java.io.*; class Singleton {  // static class  private static Singleton instance;  private Singleton()  {  System.out.println('Singleton is Instantiated.');  }  public static Singleton getInstance()  {  if (instance == null)  instance = new Singleton();  return instance;  }  public static void doSomething()  {  System.out.println('Somethong is Done.');  } } class GFG {  public static void main(String[] args)  {  Singleton.getInstance().doSomething();  } }>

出力
Singleton is Instantiated. Somethong is Done.>

getInstance メソッドでは、インスタンスが null かどうかを確認します。インスタンスが null でない場合は、オブジェクトが以前に作成されたことを意味します。それ以外の場合は、new 演算子を使用して作成します。

Javaは文字列をintに解析します

6. シングルトンメソッド設計パターンを実装するさまざまな方法

オブジェクトごとに個別の DB 接続を作成するとコストがかかる可能性があるため、複数のオブジェクトで共有される単一の DB 接続など、クラスのインスタンスを 1 つだけ必要とする場合があります。同様に、アプリケーション内に複数のマネージャーを作成する代わりに、すべての問題を処理する単一の構成マネージャーまたはエラー マネージャーを配置することもできます。

クラシック実装

このようなクラスを実装するためのさまざまな設計オプションを見てみましょう。静的クラス変数とアクセス修飾子を十分に扱える場合、これは難しい作業ではありません。

方法 1 – 従来の実装 || getInstance() を静的に実装する シングルトン方式の設計パターン

ジャワ
// Classical Java implementation of singleton // design pattern class Singleton {  private static Singleton obj;  // private constructor to force use of  // getInstance() to create Singleton object  private Singleton() {}  public static Singleton getInstance()  {  if (obj == null)  obj = new Singleton();  return obj;  } }>

ここで私たちは宣言しました getInstance() static なので、クラスをインスタンス化せずに呼び出すことができます。初めて getInstance() が呼び出されると、新しいシングルトン オブジェクトが作成され、その後は同じオブジェクトが返されます。

注記: シングルトン obj は、必要になって呼び出しされるまで作成されません。 getInstance() 方法。これは遅延インスタンス化と呼ばれます。上記の方法の主な問題は、スレッドセーフではないことです。次の実行シーケンスを考えてみましょう。

この実行シーケンスにより、シングルトン用の 2 つのオブジェクトが作成されます。したがって、この古典的な実装はスレッドセーフではありません。

方法 2 || getInstance() を同期して実装する シングルトン方式の設計パターン

ジャワ
// Thread Synchronized Java implementation of // singleton design pattern class Singleton {  private static Singleton obj;  private Singleton() {}  // Only one thread can execute this at a time  public static synchronized Singleton getInstance()  {  if (obj == null)  obj = new Singleton();  return obj;  } }>

ここで synchronized を使用すると、一度に 1 つのスレッドだけが実行できるようになります。 getInstance() 。この方法の主な欠点は、シングルトン オブジェクトの作成中に毎回 synchronized を使用するとコストがかかり、プログラムのパフォーマンスが低下する可能性があることです。ただし、そのパフォーマンスが getInstance() アプリケーションにとっては重要ではありませんが、この方法はクリーンでシンプルなソリューションを提供します。

方法 3 – 積極的なインスタンス化 ||シングルトン設計パターンの静的イニシャライザベースの実装

ジャワ
// Static initializer based Java implementation of // singleton design pattern class Singleton {  private static Singleton obj = new Singleton();  private Singleton() {}  public static Singleton getInstance() { return obj; } }>

ここでは、静的初期化子でシングルトンのインスタンスを作成しました。 JVM はクラスがロードされるときに静的初期化子を実行するため、これはスレッドセーフであることが保証されます。このメソッドは、シングルトン クラスが軽量で、プログラムの実行全体を通じて使用される場合にのみ使用してください。

方法 4 – 最も効率的 ||ダブル チェック ロックを使用してシングルトン デザイン パターンを実装する

注意してみると、オブジェクトが作成されると同期は役に立たなくなります。これは、obj が null ではなくなり、一連の操作で一貫した結果が得られるためです。したがって、obj が null の場合に getInstance() のロックを 1 回だけ取得します。このようにして、必要なものだけを最初の方法でのみ同期します。

ジャワ
// Double Checked Locking based Java implementation of // singleton design pattern class Singleton {  private static volatile Singleton obj = null;  private Singleton() {}  public static Singleton getInstance()  {  if (obj == null) {  // To make thread safe  synchronized (Singleton.class)  {  // check again as multiple threads  // can reach above step  if (obj == null)  obj = new Singleton();  }  }  return obj;  } }>

objを宣言しました 揮発性の これにより、シングルトン インスタンスに初期化されるときに、複数のスレッドが obj 変数を正しく提供できるようになります。このメソッドにより、同期メソッドを毎回呼び出すオーバーヘッドが大幅に削減されます。

7. パターンシングルトン法のユースケース

  • データベース接続: データベース接続の作成と管理にコストがかかるアプリケーションでは、シングルトンを使用してアプリケーション全体で単一のデータベース接続を維持できます。
  • 構成管理: アプリケーションのさまざまなコンポーネントからアクセスする必要があるグローバル構成設定がある場合、シングルトン構成マネージャーはこれらの設定への単一アクセス ポイントを提供できます。
  • GUI コンポーネント: グラフィカル ユーザー インターフェイス (GUI) コンポーネントまたはコントローラーの場合、シングルトンは UI の状態とアクションの管理に役立ち、単一の制御ポイントを提供します。
  • デバイスマネージャー: ハードウェア デバイスと対話する組み込みシステムまたはアプリケーションでは、シングルトンを使用してハードウェア デバイスへのアクセスを管理および制御し、競合を回避できます。
  • 印刷サービス: ドキュメントやレポートの印刷を伴うシステムでは、シングルトン印刷サービスにより印刷ジョブを調整および管理し、印刷リソースを効率的に使用できます。

8. シングルトンメソッド設計パターンの利点:

  • 名前の衝突を解決します。 名前の競合や衝突を避けるために単一制御点が必要なシナリオでは、シングルトン パターンにより、一意の名前を持つインスタンスが 1 つだけ存在することが保証されます。
  • 熱心な初期化または遅延初期化: シングルトン パターンは、即時初期化 (クラスのロード時にインスタンスを作成) と遅延初期化 (最初に要求されたときにインスタンスを作成) の両方をサポートし、ユースケースに基づいた柔軟性を提供します。
  • スレッドの安全性: 適切に実装されたシングルトン パターンはスレッド セーフを提供し、インスタンスがアトミックに作成され、複数のスレッドが誤って重複したインスタンスを作成しないようにします。
  • メモリ使用量の削減: リソースの消費が重要なアプリケーションでは、シングルトン パターンは、クラスのインスタンスが 1 つだけ存在するようにすることで、メモリ フットプリントの削減に貢献できます。

9. シングルトン設計パターンの欠点

  • テストの難しさ: シングルトンではグローバル状態が導入されるため、単体テストが困難になる可能性があります。シングルトンに依存している場合、シングルトンの状態がテストの結果に影響を与える可能性があるため、1 つのコンポーネントを分離してテストすることはより複雑になる可能性があります。
  • 同時実行性の問題: マルチスレッド環境では、シングルトン インスタンスの作成と初期化に関連する問題が発生する可能性があります。複数のスレッドが同時にシングルトンを作成しようとすると、競合状態が発生する可能性があります。
  • 限られた拡張性: シングルトン パターンでは、コードの拡張性が低下する可能性があります。後でクラスの複数のインスタンスが必要であると判断した場合、またはインスタンス化ロジックを変更したい場合は、大幅なリファクタリングが必要になる可能性があります。
  • グローバルな依存関係: シングルトン パターンはグローバルな依存関係を作成するため、シングルトンを代替実装に置き換えたり、インスタンスを提供するために依存関係注入を使用したりすることが困難になります。
  • サブクラス化が難しい: シングルトンをサブクラス化するのは難しい場合があります。通常、コンストラクターはプライベートであるため、シングルトンの拡張には追加の注意が必要であり、標準の継承パターンに従っていない可能性があります。
  • ライフサイクル管理: シングルトン パターンは、インスタンスを明示的に破棄またはリセットする必要があるシナリオを処理できない場合があります。シングルトンのライフサイクルの管理が問題になる場合があります。
  • グローバル アクセス ポイントの悪用: グローバル アクセス ポイントは利点ですが、悪用される可能性もあります。開発者は、すべてにシングルトンを使用する誘惑に駆られる可能性があり、その結果、グローバル状態が過度に使用され、モジュール性の低い設計につながる可能性があります。

10. 結論

一部のクラスでは、インスタンスが 1 つだけ存在することが重要です。システム内には多数のプリンタが存在できますが、プリンタ スプーラは 1 つだけである必要があります。ファイル システムとウィンドウ マネージャーは 1 つだけ存在する必要があります。デジタル フィルターには A/D コンバーターが 1 つあります。会計システムは 1 つの会社にサービスを提供する専用になります。クラスにインスタンスが 1 つだけあり、そのインスタンスに簡単にアクセスできるようにするにはどうすればよいでしょうか?グローバル変数を使用するとオブジェクトにアクセスできるようになりますが、複数のオブジェクトをインスタンス化できなくなるわけではありません。

より良い解決策は、クラス自体にその唯一のインスタンスを追跡する責任を持たせることです。このクラスは、(新しいオブジェクトを作成するリクエストをインターセプトすることによって) 他のインスタンスが作成できないことを保証し、インスタンスにアクセスする方法を提供できます。これがシングルトンパターンです。