デザインパターン 初めの一歩:Singleton

デザインパターンをがんばって書いてみる。JavaPerlを行き来しつつ。

Singleton :: インスタンスを1個だけに限定するデザインパターン。「そのクラスから生成されるインスタンスは1個だけしかない」という確実な保証をすることが大事だとか。

結城さんの本を参考に(というか丸写し・・・)Javaで書くと

public class Singleton {
	private static Singleton singleton =new Singleton();
	private Singleton(){
		System.out.println("インスタンスを生成しました");
	}
	public static Singleton getInstance(){
		return singleton;
	}
}

こんな風になる。生成するインスタンスをprivateにすることで、外部からイタズラできないようにする。コンストラクタはメッセージを応答するだけ。getInstance()はインスタンスを返すクライアント側はこんな感じにするらしい↓

public class Main {
	public static void main (String[] args){
		System.out.println("start");
		Singleton obj1 = Singleton.getInstance();
		Singleton obj2 = Singleton.getInstance();
		if(obj1 == obj2){
			System.out.println("obj1とobj2は同じインスタンスです");
		}else {
			System.out.println("obj1とobj2は違うインスタンスです");
		}
		System.out.println("End");
  }
}

Singleton.getInstance()する前に

	private static Singleton singleton =new Singleton();

が呼び出されてインスタンスが保持されるとのこと。この呼び出しのメカニズムがよくわかんないや。



んでPerlだとどうなるかというと
http://perldesignpatterns.com/?SingletonPattern
を参考に書くと

package Singleton;

use strict;

my $singleton;

sub getInstance{
  if(! $singleton){
    my $class = shift;
    $singleton = bless {} => $class;
  }else{
    return $singleton;
  }
}

1;

クライアントは

use Singleton;

my $child =  Singleton->getInstance();
my $child2 = Singleton->getInstance();

if($child == $child2){
  print "同じインスタンスですよ?n";
}else{
  print "違うインスタンスですよ?n";
}

exit;

のようになりました。

宙に浮いたような$singletonがなんか気持ち悪い。getInstanceメソッドを呼び出すとき、インスタンスが生成されていない場合はコンストラクトして$singletonに突っ込む。既にインスタンスが生成されていた場合は$singleton(インスタンス)を返す。

他にもうまいやり方がありそうな気がします。

  • 同じインスタンスかどうかの比較はリファレンスを==で比較するだけでいいんだよね。(同じスカラー値を持ってるから)
  • Javaのコードに合わせてgetInstanceメソッドを実装してみたけど、場合によってはnewの方がいいのかな。