31 Mayıs 2009Php Singleton Design Pattern ( OOP Yazılım Deseni )
Ben gibi bir çok kişi de geliştiriği uygulamalarda zaman zaman uygulamaların büyüklüğüne göre sınıflar yazıp kullanmışızdır. Nesne yönelimli bu yazılımda en azından benim canımı sıkan olay bazen sayfalarda tek tek yazmış olduğumuz sınıfları çağırmak zorunda kalırız. Bu durum da ister istemez uygulamanın performansına etki etmektedir zira nesne yönelimli uygulamalar yazmak hoş olsada dikkat edilmediği zaman aşırı kaynak tüketimine yol açabilmektedir.
Bu yüzden bazı yazılım desenleri ortaya çıkmıştır. Benim bu yazıda size tanıtacağım yazılım deseni ise Singleton desenidir. Singleton deseni aslında bir sınıfın sadece bir kopya olmasını amaç edinmektedir. Yani bize lazım olacak bir veritabanı sınıfı uygulamada bir kez kullanmamız gerekmektedir. Çünkü veritabanı ile başka bir işlem yapmayacağızdır. Bu yüzden de birden çok veritabanı sınıf kopyası yerine daha önceden başlatılmış veritabanı sınıfını alıp kullanmaktır. Böylelikle kaynak tüketimini de boş yere harcamamış oluruz.
Singleton desenine geçmeden önce bu desen ile ilgili birşeyi atlamamamız gerekmektedir. Bu desende illaki static tanımlı erişim metodu olmak zorundadır. Static olma zorunluluğunun nedeni ise ramde tutulması içindir. Zaten bizde aynı sınıfa farklı bir yerde ihtiyaç duyduğumuzda daha önceden tanımlanmış ise ramden alacağız yoksada yeni başlatacağız.
Şimdi öncelikle bir bilgi sınıfı yazalım. Sınıf sadece girilen değerlere göre isim ve mesleği ekrana yazdırmak olacaktır.
< ?php class bilgi { private $isim; private $meslek; public function isimGir($isim) { $this->isim = $isim; return $this; } public function meslekGir($meslek) { $this->meslek = $meslek; return $this; } public function bilgiGetir() { echo 'İsim: '.$this->isim.' Mesleği: '.$this->meslek; } } ?>
Sınıfımızı yukarıdaki gibi tanımladık böylece artık kendisine verilen bir isim ve mesleği ekrana yazdıracaktır. Sınıfımız ile ilgili bir gelin bir örnek yapalım.
< ?php include_once('bilgi.class.php'); $b = new bilgi; $b->isimGir('Yusuf Koç')->meslekGir('PHP Developer')->bilgiGetir(); ?>
evet ne yaptık bilgi sınıfını kullanabilmemiz için öncelikle sayfamıza dahil ettik ve $b = new bilgi; diyerek sınıfı başlattık. İlk etapda gayet normal gibi görünsede aynı sınıfı farklı sayfalarda da kullanmak istediğimizde yeniden çalışma sayfamıza dahil edip başlatmamız gerekecek ve kaynakta yeniden yer işgal etmiş olacağız.
İşte singleton desenide burda devreye giriyor. Sadece bir tane başlatıp devamında bu sınıf çağrılmak istendiğinde mevcut başlatılmış sınıfı bize döndürüyor.
Singleton deseni için sınıfımızı yazalım.
< ?php class Singleton { private static $sinif = array(); private static $sinifDizin = 'class'; public static $sinifSay = 0; private function __construct() { } public static function sinifOrnegiAl($sinif) { if (!(self::$sinif[$sinif] instanceof $sinif)) { include_once(self::$sinifDizin.'/'.$sinif.'.class.php'); self::$sinif[$sinif] = new $sinif; self::$sinifSay++; } return self::$sinif[$sinif]; } } ?>
Singleton sınıfımızı kısaca açıklamak istiyorum. Öncelikle sınıf içinde kullanmak üzere bazı değişkenler tanımladık. Ayrıca sınıfımızın yapılandırıcı fonksiyonunu da private olarak tanımlayarak $s = new Singleton; gibi kullanımların önüne geçmiş olduk.
sinifOrnegiAl() metodu ile kullanmak istediğimiz sınıf adını belirtiyoruz. Burda dikkat etmemiz gereken şey ben sınıf adını vererek class/sinifadi.class.php şeklinde bir dizinde tutup ordan include ettiriyorum siz kendinize göre düzenleyebilirsiniz devam edelim if bloğunda sınıf içinde static tanımlanmış sinif nesnesinin bize bildirilen sınıfın bir örneği olup olmadığına bakıyoruz eğer bir örneği değil ise istenilen sınıfı include edip başlatıyoruz ve return ile döndürüyoruz. Ayrıca burdaki $sinifSay her kullanımda bir artırarak kullanılan toplam sınıf sayısını elde ediyoruz.
Gelelim şimdi kullanımına. Öncelikle ana sınıfımızı kullanmak istediğimiz sayfalarımıza dahil ediyoruz ve Ardından aşağıdaki gibi başlatıyoruz.
include_once('class/singleton.class.php'); $bilgi = new Singleton; // Ölümcül Hata Alırsınız. Çünkü Direk Erişimi private function __construct() ile yasakladık. $bilgi = Singleton::sinifOrnegiAl('bilgi'); // Doğru olan bu. $bilgi->isimGir('Yusuf Koç')->meslekGir('PHP Developer')->bilgiGetir();
yukarıda iki satır yazdım ve açıklamalarınıda yanına yazdım. Evet böylelikle bilgi sınıfımız tanımlandı ve bir daha tekrar kullanılmak için singleton sınıfı ile çağrıldığında artık daha önce başlatıldıysa direk return etcek başlatılmadıysa başlatıp öyle return etcek.
Diyeceklerim bu kadar anlatım bozuklukları olabilir gördüğünüz yerleri bana Hakkımda kısmından mail atarak bildirirseniz gerekli düzenlemeleri yaparım.
Şimdilik Hoşçakalın…


Sevgili yusuf öncelikle eline sağlık.
Amacımız bi sınıf bi defa tanımlayarak , tüm projede kullanmak sanırım ?
Ben şöyle bi yol izliyorum onun için bi dosyam var setting.php mesela bunun içine sınıflarımı çağırıp tanımlıyorum . Ve bu setting.php dosyamı header.php(sayfanın ust parçası) alıp her yerde kullanıyorum.
Bu ikisi aynı şeyimi yapıyor acaba ?
Hoşçakal
@Gökhan Aygün
Aynı şeyi yapmıyor zira aynı şeyi yapsa bu yazılım desenleri ortaya çıkmazdı. Ayrıca senin yaptığın şekilde tüm sınıflarımız bütün sayfalara dahil olmakta ve doğal olarak ekstra sayfalar yüklenmekte ve açılış hızınada etki etmektedir.
Oysa bu yazılım deseninde çalışılan sayfada sadece ilgili sınıfı çağırmak. Yalnız şöylede diyebilirsiniz şimdi e o zaman sadece o sınıfı çağırırım aynı şeye çıkar gibi bir düşünceye kapılabilirsiniz. Burda Signleton deseniyle biz sınıfı başlatırken ram de tutuyoruz. Tekrar aynı sınıfa ihtiyaç duyulduğunda ramde daha önceden bir kaynak ayrılmış mı bu sınıf ona bakıyoruz eğer daha önceden başlatılmışsa mevcut olan sınıfı döndürüyoruz..
Yani kısacası bir sınıf kaynakta sadece bir kere çalıştırılıyor. Tekrar aynı sınıf istendiğinde ramden dönülüyor…
sağolasın güzel bir yazı olmuş
Çok güzel bir yerden başlamışsın Yusuf, tebrikler ve teşekkürler. Yazılımlarımızda sınıf kullanma, ancak yazılım desenleri uyarınca kullanılırsa daha efektir kullanılabilir, yoksa OOP avantajı yitirilir. Yazılım desenleri bu nedenle çok önemli olmalarına karşın, haklarında türkçe kaynakğın az bulunması sebebiyle, senin gibi yazarlara çok iş düşmektedir.
Yazın temiz ve anlaşılır olduğu için tebrik ederim. Diğer desenler hakkında da yazılarına devam etmeni dilerim.
Harika Olmuş Yusufum Ellerine Sağlık
Anladım(ben farklı anladım ilk okuduğumda demek bişeyi iki defa okumam lazım) ve bundan sonra bunu kullanıyorum
gerçekten elinize sağlık. Tasarım desenleriyle ilgili başka yazılarınızı sabırsızlıkla beklemekteyim.
@gökhan
tasarım desenlerinde önemli noktalardan biri her desen bir problemi çözmek için modellenmiştir. Bunu göz önünde bulundurarsak her uygulamada bu deseni kullanmak bizim için dez avantaj olur. Hangi deseni ne zaman nerede kullanacağımızıda iyi düşünmek gerekiyor diye düşünüyorum.
Merhaba;
Anladığım kadarıyla Singleton deseni bir objeden yalnızca bir tane yaratıyor, ve her sayfada yaratılan o objenin fonksiyonları kullanılıyor. Böylece her sayfada ayrı bir obje yaratmaktan kurtuluyoruz. Peki her kullanıcı için tek bir obje yaratmak istesem ? Örneğin sayfama giren her kullanıcı daha önce yaratılan tek bir obje’nin fonksiyonlarını kullansa, her kullanıcı için ayrı bir obje yaratmasak ? Ram’de tek bir obje olsa ve bütün kullanıcılar o tek objenin fonksiyonları ile işlem yapsa, performansta artış olmaz mı ? Böyle bir desen var mı ? Singleton bunu sağlıyor mu ? Static olarak tanımlanan değişken ve fonksiyonlar her kullanıcı için mi tanımlanıyor yoksa, ram’de tek bir yer açıp ordan mı kullanıyor ?
Ayrıca eğer zamanınız varsa;
Abstract Factory Creates an instance of several families of classes
Builder Separates object construction from its representation
Factory Method Creates an instance of several derived classes
Prototype A fully initialized instance to be copied or cloned
Bu desenlerin nasıl çalıştığına dair en ufak bilgi bile çok yardımcı olucaktır.
Teşekkürler
Teşekkürler.
Design patternlerin ne olduğunu anlayamamıştım.
Bu ram tüketimi hakkında devamlı kafa yoruyodum. Şöylemi yapsam böylemi yapsam. Bu makaleniz çok yararlı oldu.
İyi akşamlar…
Çok güzel bir yazı olmuş ellerine sağlık. Bu arada yazıda herhangi bir anlatım bozukluğu hissediliyorsa verdiğin örnekte self:$sinif ile $sinif değişkenlerinin birbiriyle karıştırılmasından kaynaklanıyor
Ben ilk bakışta self’i umursamadım, sonradan fark ettim
evt çok güzel makale olmuş bende bu tarz bişi kullanıyordum ve bir arkadaş yazmış ust.php ekledim tüm sınıfları çalıştırıyor diye evt oda bi yöntem fakat sistemi aşırı derecede yoyar yani her sayfaya girildiginde başlatılmış sınıfları geziyor ve hafızasında tutuyor yusuf koç’un yaptıgı yöntem pratik ve kullanışlı kullanışlı teşekkürler.. şunu denemedim ama şu şekilde yapabiliriz
function SinifBaslat($adi,$sinif,$sinifadi)
{
//burada tanımlımı diye bakıyoruz çünkü eklemezsek rfi açıgı dogrurabilir.
if(isset($sinif)){
include(“$sinif”);
}else{
echo ‘Belirttiginiz Sınıf Bulunamadı‘;
}
$adi = new $sinifadi;
}
Teşekkürler Raiden, on numero ilham verdin (:
Çok güzel bir yazı olmuş. Paylaşımın için teşekkürler.
Fatal error: Call to private Singleton::__construct() from invalid context in C:\xampp\htdocs\forbidden\deneme\index.php on line 3
ne yapmaya çalıştında aldın bu hatayı ? hatayı yazman bişey ifade etmiyor 3. satırdaki kodun nedir ?
3. Satırdaki kod
$bilgi = new Singleton; // Ölümcül Hata Alırsınız. Çünkü Direk Erişimi private function __construct() ile yasakladık.
@kaan
ben örnek görülmesi açısından o satırı yazdım ve belirtmişim zaten hata alırsınız diye. o satırı sil ve öyle devam et.
Tamam teşekkürler.
Merhaba, öncelikle eline sağlık, güzel anlatım ve konu olmuş. Ben bir yerde takıldım, Bir den fazla class nasıl çağırabiliriz?
Bu konu da yardımcı olursanız, memnum olurum
@BeyazKan
birden fazla class derken neyi kastettiniz anlayamadım.
Merhabalar
isimGir(‘Yusuf Koç’)->meslekGir(‘PHP Developer’)->bilgiGetir();
?>
Yukarıdaki gibi zincirleme bir kod neden yazdınız acaba ?
yani return $this; gönderip sonra;
$b->isimGir(‘Yusuf Koç’)->meslekGir(‘PHP Developer’)->bilgiGetir();
diye çağırınca ne değişmiş oluyor ? Yani bu tip bir kullanım ne işimize yarar. Çok merak ettim teşekkürler
@Gökhan
kullanmamın herhangi bir nedeni yok. Bu tip zincirleme metotlarının normal kullanımdan bir farkı yok. Ama yine de Query oluştururken gayet kolay oluyor.
Örneğin:
Yanıtınız için teşekkürler. Hemen bahsettiğiniz gibi zincirleme bir sql üreteci yazdım çalıştı.
Yanlış anlamadıysam singleton deseni php’nin çalıştığı sunucuda diğer kullanıcılar hali hazırda bir sınıfı türettirmişlerse, yani belleğe yüklenmişse bir daha yüklenmesini önlüyor öyle değil mi ?
@Gökhan
Amaç zaten bir sınıfın bir kere yüklenmesi ve tekrar çağrıldığında bu başlatılmış sınıfı döndürmesidir.
bir nevi cache üzerinden çalışmak anlamına geliyor. gayet kullanışlı. özellikle yapmak istediğim projede veritabanıdaki değerleri ilk açılışta ajax ile arkaplanda çağırıp singleton içerisinde muhafaza edebilirim.
acaba bu şekilde işlemcinin 2 çekirdeğinide kullanmış olurmuyum yoksa sadece kuyruğa işlem eklemiş mi olurum.