PHP – singleton pattern vs clone

Class Test{
       /**
	 * Örnek Değişken
	 */
	public $sampleVariable = NULL;

	/**
	 * Singelton bir yapı kullanılmaktadır
	 * @var Test
	 */
	private static $_instance;
       /**
	 * Singelton yapıyı desteklemek için private constructor yarattım içi boş.
	 */
	private function __construct(){

	}

	/**
	 * Singelton yapıyı destekleyen getInstance metodu
	 * @return Test
	 */
	public static function getInstance(){
		if (self::$_instance == null) {
			self::$_instance = new Test();
		}
		return self::$_instance;
	}
}

Yukarıdaki kod basitçe bir singleton mimariyi gösteriyor.

Burada ben

 $test = new Test()

yaratamıyorum. Çünkü constructor method’un erişilebilirliği “private” olarak belirlenmiş.
Yani ancak bu sınıfı

$test = Test::getInstance()

diyerek kullanabilirim.

Peki gelin görün ki, unuttuğumuz bir şey var.

Php’de “clone” diye bir obje kopyalama özelliği var. Nedir bu?

$a = new stdClass();
$k = $a;

dediğimizde, $a->var = 5 dediğimizde, $k da aynı şekilde değişiyor. yani bu ikisi aynı objeyi işaret ediyor.

Ancak

$a = new stdClass();
$k = clone $a;

Yazdığımızda ise, artık $k, $a nın en son halinden kopyalanıp yeni bir obje olarak oluşturuluyor.

Yani ben ilk örnekte,

$test = Test::getInstance();

yazdıktan sonra bir yerlerde
$anotherTest = clone $test;
dersem, artık yeni bir obje türetebilmiş oluyorum.

Buyrun deneyin :

$test = Test::getInstance();
$anotherTest = clone $test;

$test->sampleVariable = 5;
$anotherTest->sampleVariable = 10;

var_dump($test);
var_dump($anotherTest);

Birbirinin aynısı olmayan, aynı objenin farklı 2 instance’ını singleton mimaride de yapabilmiş oldum.

Sonuç : Demek ki, PHP de singleton mimarisi güvenilir değildir. Class’ın içerisine ancak private bir __clone metoru tanımlayınca güvenli oluyor. (@edit adil ilhan’ın yorumuna istinaden)
Yine de güzel bir design patterni olarak beğeniyorum. Ancak bilinçli kullanmanızı tavsiye ederim.