オブジェクト指向プログラミングのプログラミング手法で、「singleton(シングルトン)」と呼ばれる手法があります。
この手法は、プロジェクト内で共通的に使われるインスタンスを1つだけ予め作成し、外部のクラスにはそのインスタンスを使用させる、という手法です。
この手法を学んだ時に「インスタンスを1つにすれば良いなら、クラス変数やメソッドをstaticにするだけで良いのでは?」と思ったので、試しにテストコードを書いてみました。
単純なstaticでは使用者側で好きにインスタンスを作成できる(実態としては1つ)のですが、singletonとしてインスタンスを作成すれば使用者側でのインスタンス作成を防ぎ、明示的にインスタンスを1つにできることを確認しました。
【テストコード】
・StaticMemory.java
public class StaticMemory {
private static int num = 0;
public static void setNum(int arg) {
num = arg;
}
public static int getNum() {
return num;
}
}
・SingletoneMemory.java
public class SingletoneMemory {
private static int num = 0;
private static SingletoneMemory instance = new SingletoneMemory();
private SingletoneMemory(){
// インスタンスを生成
}
public static SingletoneMemory getInstance(){
return instance;
}
public static void setNum(int arg) {
num = arg;
}
public static int getNum() {
return num;
}
}
・MemoryTestMain.java
public class MemoryTestMain {
// 要件:最新の値をメモリに保持したい
@SuppressWarnings("static-access")
public static void main(String[] args) {
int recentNum = 0; // 最新の値
// 普通のStaticなクラスを使った場合
recentNum = 1;
StaticMemory.setNum(recentNum);
// 使う側がオブジェクトを作れてしまう
StaticMemory instance1 = new StaticMemory();
recentNum = 2;
instance1.setNum(recentNum);
StaticMemory instance2 = new StaticMemory();
recentNum = 3;
instance2.setNum(recentNum);
// Staticなので実際には何れのオブジェクトも同じアドレスを指す
System.out.println("元のStaticクラス:"+StaticMemory.getNum());
System.out.println("作ったオブジェクト1:"+instance1.getNum());
System.out.println("作ったオブジェクト2:"+instance2.getNum());
// Singletoneなクラスを使った場合
// オブジェクトがprivateなので外部から作れない(下記はエラー)
// SingletoneMemory instance3 = new SingletoneMemory();
// 唯一のオブジェクトを取得する必要がある
recentNum = 4;
SingletoneMemory.getInstance().setNum(recentNum);
System.out.println
("Singletoneクラス:"+SingletoneMemory.getInstance().getNum());
}
}
【実行結果】
元のStaticクラス:3
作ったオブジェクト1:3
作ったオブジェクト2:3
Singletoneクラス:4
いかがでしたでしょうか。
「singleton」は、GoFの23個のデザインパターンの内の1つに数えられる手法です。
デザインパターンはオブジェクト指向プログラミングのプログラミング手法をまとめたものであり、効率的なプログラミングを行う上で有効ですので、これからも紹介していくと思います。
では、また次回!


コメント
すみません通りすがりでたまたま見たのでコメントしますが、
staticしかないメソッドのクラスの方にも
privateのコンストラクタを作れば 「使用者側で好きにインスタンスを作成できる」を防げるのではないでしょうか?
このままだと
「単なるstaticとsingletoneパターンの違い」 という記事としては主張が弱いような気がします。
class StaticMemory {
private StaticMemory() {
}
private static int num = 0;
public static void setNum(int arg) {
num = arg;
}
public static int getNum() {
return num;
}
}
コメントありがとうございます。
コードを実際に書いて確認しましたが、確かにご指摘通りでした。
そもそも、Singletonの書き方に倣ってgetInstanceメソッドを用意したとしても、
SingletoneMemory.getInstance()
を
SingletoneMemory
で代替できますね。
(インスタンスが一つしか生成されないので)
なぜSingletonパターンでgetInstanceメソッドを用意することが推奨されるのか、分からなくなってきました。
(単なる流儀なのか、私が何か勘違いしているのか…)
私の不勉強で申し訳ないのですが、また気付いたことがあれば書かせていただきます。