どうも、とがみんです。
「オブジェクト指向における再利用のためのデザインパターン」という本を参考にしつつ、Singletonパターンについて調べたのでまとめていきます。
Singletonパターンとは?
あるクラスに対して、インスタンスが一つしかないことを保証し、グローバルにアクセスするための方法を提供するプログラムのデザインパターンの一つです。
新しいオブジェクトを生成に関する要求を制御することで、インスタンスが1つしか生成されないように保証します。
クラスに対してインスタンスが1つしか存在してはならず、また、クライアントがそのインスタンスをアクセスポイントを通してアクセスできるようにしなければならない場合、
唯一のインスタンスがサブクラス化により拡張可能で、クライアントが、拡張されたインスタンスをコードの修正なしに利用できるようにしたい場合に適用します。
サブクラス化:オブジェクト指向プログラミングにおいて、既存のクラスの機能や構造を継承して新しいクラスを作成すること。
Singletonパターンをどのように実装するか
実装方法1
1 2 3 4 5 6 7 8 9 10 11 12 | final class Singleton{ private static Singleton instance; //コンストラクタ private Singleton(){} public static synchronized Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } } |
この実装方法の場合、コンストラクタはprivateで定義されているため、他のクラスによってSingletonクラスのインスタンスを生成することができません。
このクラスを生成したい場合、getInstance()メソッドを利用し、インスタンスを生成します。
このメソッドは、最初に呼び出されたときだけインスタンスを生成し、2回目以降に呼び出されたときは最初に生成したインスタンスを返すようにつくられています。
そのため、プログラム中にSingletonクラスのインスタンスが1つしか存在しないことが保証されます。
getInstance()メソッドに、synchronizedが指定されている理由は、複数のスレッドからほぼ同時にgetInstance()メソッドを呼び出されてしまった場合に、複数のインスタンスが生成されてしまう危険性をなくすためです。
ただし、synchronizedによるパフォーマンス劣化がデメリットです。
コンストラクタ:クラスからオブジェクトを作成した際に、自動的に実行されるメソッドのこと。
実装方法2
1 2 3 4 5 6 7 | final class Singleton { private static final Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return Singleton.instance; } } |
staticフィールドの初期化処理は、クラスがロードされたときに1度しか行われないため、スレッドセーフかどうかを意識する必要がなくなります。
そのため、実装1よりもパフォーマンスがよくなるメリットがあります。
しかし、getInstance()メソッドが呼ばれるときにインスタンスかされるのではなく、クラスファイルロード時にインスタンス化されるため、意図しないタイミングでそれが行われてしまう懸念があります。
実装方法3
1 2 3 4 5 6 7 8 9 | final class Singleton { private Singleton() {} private static class SingletonHolder { private static final Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } } |
実装方法2では、クラスロード時にインスタンス化されるため、プログラマーが意図しないタイミングでインスタンス化されてしまう可能性があるという問題がありましたが、
上記のように記述することで、getInstance()が呼び出されたタイミングで、SingletonHolderクラスがロードされ、Singletonクラスがインスタンス化されます。
この記述が現在推奨されているようです。
まとめ
Singletonパターンについてまとめてきました。