ChatGPTでデザインパターンを学ぼうと思い立ち、記録していきます。
1つ目のデザインパターンはシングルトンパターンです。
シングルトンパターンとは
ChatGPT
「クラスのインスタンスを1つだけ作る」というルールを作る方法です。
例えば、学校で校長先生が1人だけなのと同じように、何度呼んでも同じ校長先生(インスタンス)が返ってくるようにします。
→ システム全体で唯一のものを扱いたいときに使うパターン。
ユースケース
ChatGPT
こんな時に使います
- 設定管理:アプリ全体で共有する設定を1か所で管理したいとき
- ロギング:アプリ全体で同じログファイルに書き込みたいとき
- データベース接続:複数の接続を防ぎ、効率よく使いたいとき
→ 設定はシステム全体で1つ。同期処理的なことにも使える。
サンプルプコード
※サンプルコードは、ChatGPTに示してもらったものを自分なりに解釈して記載しています。
シングルトンクラス
package singleton;
public class SingletonSample {
// 唯一のインスタンスを保持
private static SingletonSample instance;
private String name;
// コンストラクタをプライベートで宣言
// 外部からのインスタンス化を禁止
private SingletonSample() {}
// 唯一のインスタンスを取得するためのメソッド
public static synchronized SingletonSample getInstance() {
if (instance == null) {
instance = new SingletonSample();
}
return instance;
}
// setter
public void setName(String newName) {
instance.name = newName;
}
// getter
public String getName() {
return this.name;
}
}
ポイント
- staticなクラス変数としてインスタンスを保持
- コンストラクタをprivateで宣言することで、外部からインスタンス化を禁止
- getInstance()メソッドで唯一のインスタンスを返す
- getInstance()はマルチスレッド環境でも安全にインスタンス取得できるよう、synchronizedメソッドとしている
呼び出し側
import singleton.SingletonSample;
public class App {
public static void main(String[] args) throws Exception {
// 1.シングルトンパターン
callSingletonSample();
}
/**
* 1.シングルトンパターン
* 唯一のインスタンスを生成する
*/
private static void callSingletonSample(){
System.out.println("---1つ目のインスタンス取得処理---");
SingletonSample singletonA = SingletonSample.getInstance();
singletonA.setName("校長 太郎");
System.out.println("1つ目のインスタンス:"+singletonA.getName());
System.out.println("---2つ目のインスタンス取得処理---");
SingletonSample singletonB = SingletonSample.getInstance();
System.out.println("2つ目のインスタンス:"+singletonB.getName());
System.out.println("---2つ目のインスタンスで名前変更---");
singletonB.setName("校長 花子");
System.out.println("1つ目のインスタンス:"+singletonA.getName());
System.out.println("2つ目のインスタンス:"+singletonB.getName());
}
}
実行結果
---1つ目のインスタンス取得処理---
1つ目のインスタンス:校長 太郎
---2つ目のインスタンス取得処理---
2つ目のインスタンス:校長 太郎
---2つ目のインスタンスで名前変更---
1つ目のインスタンス:校長 花子
2つ目のインスタンス:校長 花子
ポイント
- singletonA、singletonBは同じオブジェクトを指し示していることがわかる
気になったこと
デザインパターンの初めの一歩で、必ず出てくるシングルトンパターン。
staticで宣言すればクラスに唯一の変数を用意することもできます。
シングルトンパターンの必要性をもう少し聞いてみました。
static変数を使えば、同じクラス内でその変数が共有されるため、状態を1つに保つことが可能です。シングルトンパターンが必要なケースは
- 動的な初期化や管理が必要:オブジェクトの初期化や制御をクラス自身が行える
- 遅延初期化のサポート:インスタンスが必要になるまで生成を遅らせることができ、リソースを節約できる
- 制御と拡張性:インスタンスの生成や管理に特定のロジック(例:スレッドセーフ性)を追加できる
- 状態の隠蔽(カプセル化):インスタンスへのアクセスをgetInstance経由に限定することで、内部の状態を適切にカプセル化できる
- インターフェースやポリモーフィズムとの相性:シングルトンはクラスのインスタンスを返すので、インターフェースを使って依存性注入(DI)と組み合わせることができる
→ 単純な状態管理だけでなく、同期をとって、アクセスを制限するような処理を実装したり、複雑な初期化処理を実装したいときなどに利用できる。公開するメソッドを限定することで、利用する側がメソッドの中身がどうなっているかを気にせず利用することができる。
関連