3 Ekim 2009Php Prototype Design Pattern
Bazen oluşturduğumuz sınıfları tekrar tekrar kullanmak isteyebiliriz. Örneğin Ali’nin not bilgilerini getiren bir notgetir sınıfını aynı sayfada bir de Veli için kullanmak istediğimiz zaman notgetir sınıfını bu seferde Veli için new operatörü ile başlatıp erişim sağlardık.
Bu da yani tekrar new operatörü ile sınıfı başlatmak yine bellekte bir miktar yerin notgetir sınıfı için yeniden yer ayrılmasına neden olacaktı. Prototype pattern ile daha önceden new ile başlatılan sınıfın bir kopyasını alarak aynı sınıfı tekrar new operatörüyle başlatmaktan kaçınmış ve performans artışı sağlamış oluyoruz.
Bir örnekle bahsedelim hemen.
< ?php class notgetir { private $isim; private $not; public function isim($isim) { $this->isim = $isim; return $this; } public function not($not) { $this->not = $not; return $this; } public function getir() { echo $this->isim.' \'nin Notu: '.$this->not; } public function __clone() {} } ?>
Yukarıda ismi ve notu belirtilen kişinin ismini ve not değerini ekrana yazan bir sınıf tanımladık. Burda yabancı olunulan metot __clone() dur. Bu metot bu sınıfın kopyalanabilir olmasını sağlar. Aslında yazmasakda kopyalanabilir ama bazen bazı durumlarda tanımlanan sınıfın kopyalanması başımıza iş açabilir o yüzden sınıfların kopyalanma özelliğini kapatmak için bu __clone() metodunu ya private yaparız ya da içine exception ya da exit ile bir uyarı mesajı koyabiliriz.
Konuyu dağıtmadan devam edelim. Şimdi biz Ali için bu sınıfı çağıralım ve verilen bilgiler doğrultusunda bu bilgileri ekrana yazsın
< ?php $not = new notgetir; $not->isim('Ali')->not(90)->getir(); ?>
yukarıda sınıfı new operatörü ile başlattık ve hangi öğrencinin notunu istiyorsak onun ismini ve notunu set edip getir metodu ile ekrana yazdırdık. Şimdide aynı işlemi Veli için yapalım.
< ?php $not2 = new notgetir; $not2->isim('Veli')->not(100)->getir(); ?>
Şimdi yukarıda ne yaptık aynı sınıfı tekrar new operatörü ile başlattık ve ram de bir miktar daha yer kapladık ve bu da haliyle zamanla kaynak tüketimine yol açıp performansı düşürecektir.
Aynı örneği şimdide bir prototipini oluşturarak yapalım. Aslında burda yapacağımız tek işlem daha önce Ali için başlatılmış sınıfın bir kopyasını almak.
< ?php $not2 = clone $not; $not2->isim('Veli')->not(100)->getir(); ?>
Burda clone opetörü ile daha önce başlatılan notgetir sınıfının bir prototipini aldık yani kopyaladık böylelikle tekrar sınıfı başlatmaktan kurtulmuş olduk.
Bazılarınız $not2 = $not kısmı ile de yapılabilir bu diyebilir ama clone ile bu farklıdır. Aslında $not2 = $not demek $not2 nin $not a eşit olduğu anlamına gelir yani kopyasını almak değildir. Daha iyi anlayabilmek için aşağıdaki örneğe bakabilirsiniz.
< ?php $not = new notgetir; $not->isim('Ali')->not(90)->getir(); $not2 = $not; $not2->getir(); $not3 = clone $not; $not3->getir(); ?>
Burda not2 $nota eşitleniyor ve getir metodu çağrıldığında ekrana Ali’nin notu 90 yazarken $not3 ile yine getir metodu çağrıldığında ekrana hiç bişey yazmayacaktır. Çünkü biz not3 değişkenine $not un kopyasını aldık.
Hasta halimle bu kadar bahsedebildim. Anlam bozukluğu veya anlayamadığınız yerler var ise çekinmeden sorabilirsiniz.


Çok güzel bir yazı teşekkürler. Javascriptteki prototype olayı da bununla aynı şey mi ?
güzel bir anlatim olmus ancak en sondaki örnekte sizin de dediginiz gibi
“not3 değişkenine $not un kopyasını aldık”
öyleyse ekrana “Ali ‘nin Notu: 90″ yazar. Ekrana hicbir sey yazmayacagi dogru degil.
@Cahit pardon doğru söylüyorsunuz. Clone ile nesne kopyalanıyor yani burdaki amaç tekrar bir new operatörü kullanılmıyor. hata için teşekkürler
$not2 = $not; şeklinde yapılan işlem $not referans ettiği hafızaya $not2′yi de referenscı olarak atamaktır diye açıklarsak daha doğru olur
$not2->isim(‘Kamil’)->not(100);
$not->getir();
clone ile new arasındaki fark, new bize değerleri boş olan bir nesne üretir, clone ise adı üstünde değerleri referans gösterilen nesnenin değerleri ile doldurularak getirilir. ikiside hafızada ayrı ayrı yer kaplarlar.
@Kamil Hocam
Yanılıyorsunuz. Prototype alınmış bir sınıf bir daha başlatılmaz. Mevcut başlatılmış sınıfın kopyasını döner ama hafızada yer kaplamaz.
Örneklersek.
Eğer senin dediğin gibi clone edilmiş bir sınıf yeniden başlasaydı counter 2 çıkması gerekirdi ama 1 çıkmaktadır. Dolayısıyla sınıf başlatılmıyor.:)
——————————–
$n = new Demo();
//$b = clone $n;
echo memory_get_usage();
——————————–
Sonuç : 59632
clone kullandığımızda ise
——————————–
$n = new Demo();
$b = clone $n;
echo memory_get_usage();
——————————–
Sonuç: 60128
mantıken de zaten ayrı bir hafıza ayrılması lazım, çünkü yeni nesne oluşturuluyor, ama clone kullanılırken yapıcı fonksiyon çağrılmıyor.
@Kamil
Hocam yazının en başında da zaten demişim clone yaparken yeniden başlatmak için ayrılan zamandan tasarruf ediyoruz.
Merhaba çok güzel bir anlatım olmuş teşekkürler. Fakat aşağıdaki cümlede belirttiğiniz tanımlamaları biraz daha açabilirmisiniz ?
“Aslında yazmasakda kopyalanabilir ama bazen bazı durumlarda tanımlanan sınıfın kopyalanması başımıza iş açabilir o yüzden sınıfların kopyalanma özelliğini kapatmak için bu __clone() metodunu ya private yaparız ya da içine exception ya da exit ile bir uyarı mesajı koyabiliriz. ”
Mesela ne gibi işler açabilir ? Hangi durumlarda hangisini kullanırız ?