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.

14 Comments

    PHP – singleton pattern vs clone | Anil's Blog

    […] /** * Singelton bir yapı kullanılmaktadır * @var Preferences */ private static $_instance; /** * Singelton yapıyı deste… Devamı için : PHP – singleton pattern vs clone […]

    PHP – singleton pattern vs clone | Kara Kule

    […] /** * Singelton bir yapı kullanılmaktadır * @var Preferences */ private static $_instance; /** * Singelton yapıyı deste… Devamı için : PHP – singleton pattern vs clone […]

    PHP – singleton pattern vs clone | Murat SAÇ

    […] /** * Singelton bir yapı kullanılmaktadır * @var Preferences */ private static $_instance; /** * Singelton yapıyı deste… Devamı için : PHP – singleton pattern vs clone […]

    PHP – singleton pattern vs clone | Gökhan Tunçkale | Blog

    […] /** * Singelton bir yapı kullanılmaktadır * @var Preferences */ private static $_instance; /** * Singelton yapıyı deste… Devamı için : PHP – singleton pattern vs clone […]

    PHP – singleton pattern vs clone | Musa Usta'nın Yeri

    […] /** * Singelton bir yapı kullanılmaktadır * @var Preferences */ private static $_instance; /** * Singelton yapıyı deste… Devamı için : PHP – singleton pattern vs clone […]

    PHP – singleton pattern vs clone | Lé Blog

    […] /** * Singelton bir yapı kullanılmaktadır * @var Preferences */ private static $_instance; /** * Singelton yapıyı deste… Devamı için : PHP – singleton pattern vs clone […]

    PHP – singleton pattern vs clone | Boğaç Aslanyürek

    […] /** * Singelton bir yapı kullanılmaktadır * @var Preferences */ private static $_instance; /** * Singelton yapıyı deste… Devamı için : PHP – singleton pattern vs clone […]

    PHP – singleton pattern vs clone | yusufozkay

    […] /** * Singelton bir yapı kullanılmaktadır * @var Preferences */ private static $_instance; /** * Singelton yapıyı deste… Devamı için : PHP – singleton pattern vs clone […]

    PHP – singleton pattern vs clone | kodluyorum

    […] /** * Singelton bir yapı kullanılmaktadır * @var Preferences */ private static $_instance; /** * Singelton yapıyı deste… Devamı için : PHP – singleton pattern vs clone […]

    Adil İlhan

    PHP de singleton mimarisi güvenilirdir.

    Bir yerlerde clone yapılarak nesnenin kopyasının daha oluşmasından endişe duyuyorsanız class’ınızın içine private function __clone() {} yazarak __clone magic method’unu private olarak eklemelisiniz.

    Böylece nesneniz clone’lanmaz. Eğer private bir şekilde __clone methodunu yazarsanız ve nesneyi clone’lamaya çalışırsanız PHP Fatal Error verecektir.

      Emre Macit

      Yanıtınız için teşekkürler. Bu işleri (phpunit te test işlemleri) yaparken aklıma gelmemiş.

    engin

    singleton güvenli mi değil mi?

    Emre Macit

    singleton classta __clone metodunu override etmeniz halinde güvenlidir. Aksi takdirde clone’layarak etrafından dolaşmış olursunuz, ve singleton mantığına aykırı hareket edebilmiş olursunuz.

engin için bir cevap yazın Cevabı iptal et