Konuyu Oyla:
  • Derecelendirme: 5/5 - 1 oy
  • 1
  • 2
  • 3
  • 4
  • 5
Tasarım Desenleri : Singleton Design
#1
Hiç projenizin tamamında "şu nesneden sadece 1 tane üretilebilsin, başka da üretilemesin" dediğiniz anlar oldu mu? 

Problem

Proje büyüdükçe yönetilmesi gereken nesnelerin sayısı da çoğalıyor. Haliyle bu durum bazen karmaşaya da sebep olabiliyor. Fakat bazende öyle durumlar oluyor ki nesne sayısı çok olmasa bile bazı nesnelerin sadece bir kere üretilmesi işi çözüyor. 

Projede tek başınızayken bu tarz nesneleri idare etmek nispeten kolaydır, zira kaynak koda hakimsinizdir. Sonuçta birden fazla kez oluşturmazsınız olur biter... Peki, durum öyle değilse, yani unutursanız, veya projeye başkaları dahil olduysa o zaman ne yapılacak? İzlenecek yol belli değilse zamanla kaynak koddaki zarafetin yavaş yavaş yerini kaosa bıraktığı görülür...

Çözüm

Bu tarz, sadece bir kere oluşturulması gereken bazı nesneleriniz için Singleton Desenini kullanmak yeterli... Örnek vermek gerekirse, ben bazı projelerimde o projenin kişiliğini oluşturan belli başlı değişken gruplarını tek bir nesnede toplar ve o nesne üzerinden içeride projeyi yönetirim. Misal, kullanıcının oturum bilgileri veya o an hangi firma bilgileriyle çalışıldığını tutmak gibi örnekler verilebilir. Siz de bu tarz bir şeye ihtiyaç duyuyorsanız bu tasarım örneğini kullanmanızı tavsiye ederim.

Nasıl?

Singleton tipi bir nesne tanımı yapmanın sıradan bir sınıf tanımı yapmaktan pek bir farkı yoktur. Fark, özünde Create yerine GetInstance kullanılmasını sağlamaktadır. Nesneyi doğrudan Create etmeye kapatmak, ve bunun doğuracağı boşluğu da bu işlevi (yani Create'i) ikame edecek şekilde bir GetInstance fonksiyonu yazmaktır. 

Örnek

type
  TSingletonOrnegi = class                        // Bilinen şekilde sade, basit bir sınıf tanımı, yani hepimizin bildiği TObject'ten türetilmiş bir sınıf...
  strict private                                  // Nesne dışından erişilemeyecek olan unsurlarımızı bu bölgede tanımlıyoruz
    constructor Create;                           // Böylece Kod yazarlarının bunları doğrudan kullanmalarını engellemiş oluyoruz.
    class var FInstance: TSingletonOrnegi;        // Nesne dışından erişilemeyen bu sınıf değişkeni, bizim, nesnenin "Tekilliğini" sağlamamıza yarayacak.
  public                                          // Herkese açık, ortaklaşa kullanılabilecek unsurlarımızı da bu bölgede tanımlıyoruz...
    class function GetInstance: TSingletonOrnegi; // Nesne "yoksa" üretir, "varsa" mevcut nesneye erişir... Bu fonksiyonun veri tipi sınıfın kendisidir...
  end;

implementation

{$R *.dfm}

{ TSingleton }

constructor TSingletonOrnegi.Create;
begin
  // Bu oluşturucu, "Strict Private" bölümünde tanımalndığı için dışarıdan doğrudan kullanılamaz.
  // Dolayısıyla doğrudan çağırılsa bile herhangi bir tepki vermeyecektir.
  inherited Create;

  { BU NOKTADA KOD YAZARLARINA GETINSTANCE METODUNU KULLANMALARI YÖNÜNDE BİR HATIRLATMA YAPMAK GEREKEBİLİR...}

  // Bunu test etmeniz amacıyla ekledim, silebilirsiniz.
  ShowMessage('OnCreate');
end;

class function TSingletonOrnegi.GetInstance: TSingletonOrnegi;
begin
  // Makalemizin can alıcı yordamı aslında burası, devam eden satırlarda bu nesnenin bir örneğinin oluş olmadığı sorgulanıyor
  // Yoksa hemen bir adet üretiliyor.
  // Varsa herhangi bir üretim söz konusu değil.
  if (FInstance = nil) then FInstance := TSingletonOrnegi.Create();

  // Sonrasında da sonuç değeri olarak örneğin kendisini dışarı veriyor...
  Result := FInstance;

  // Bunu da test etmeniz amacıyla ekledim, silebilirsiniz.
  ShowMessage('OnInstance');
end;

Ne Yaptık?

Görüldüğü gibi TSingletonOrnegi adlı nesnemizin constructoru olan Create yordamını Strict Private bölümüne taşıyarak dışarıdan erişime kapattık. Artık Create yordamı sadece nesnenin içerisindeki diğer metodlar tarafından ulaşılabilir hale geldi. Böylece Singleton sistematiğinin ilk adımını tamamlamış olduk. 

Singleton deseninin ikinci adımında ise Class Variable yapısını kullandık. Bildiğiniz üzere bir sınıf içerisindeki herhangi bir fonksiyon, prosedür, özellik, nitelik veya değişken tanımının başında class ibaresi getirilmişse bilinki nesnenin o kısmını nesneyi create etmeden, doğrudan kullanabilirsiniz. Bunu bir nevi sınıfın global bir değişkeni gibi düşünebilirsiniz... (Bunun mekaniğine bu makaleye yorum yazacak olan arkadaşlar mutlaka değinecektir diye düşünüyorum...)


Kaldığımız yerden devam edecek olursak; devamında da FInstance adlı TSingletonOrnegi tipinde bir sınıf değişkenini yine Strict Private bölümünde  tanımladık. Bu bölgede tanımlamamızın iki sebebi var. Birincisi nesne henüz ortada yokken bile biz bu nesnenin bir kopyası üretilmiş mi kontrol edebilelim. İkincisi ise bu değişkene dışarıdan müdahale olmasın, sadece sınıfın kendi içinden erişilebilsin...

Bu sayede biz, sınıfımızın çalışma esnasında bir örneğinin oluşturulup oluşturulmadığını kontrol edebilir hale gelmiş olduk. 

Son olarak, public bölümünde yine veri tipi TSingletonOrnegi olan bir Class Function tanımladık. Yukarıda belirttiğim mekanizma üzerinden nesnemizin daha önceden üretilip üretilmediğini sorgulayan, üretilmemişse de Strict Private bölümüne taşıdığımız Create oluşturucusunu çalıştıran bir fonksiyonla tasarımımızı tamamlamış olduk.

Kullanımı

Kısa cevap aşağıdaki gibi

Tek := TSingletonOrnegi.GetInstance;

Uzun cevap ise şöyle;

Şimdi bu örneğin nasıl kullanıldığını inceleyelim. Bunun için ben boş bir VCL Projesi oluşturup formun üzerine 2 adet TButton ve bir adet TMemo nesnesi ekledim. İlk butona bu örneğin normalde nasıl kullanılması gerektiği ile ilgili bir kod yazdım. İkincisine ise normalde bir sınıfı oluştururken hangi yolu izliyorsak onu yazdım. Anlatım bütünlüğünü bozmamak adına kaynak kodun tamamını aşağıya ekledim ve kaynak koda bazı açıklamalar ekledim.

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TSingletonOrnegi = class                        // Bilinen şekilde sade, basit bir sınıf tanımı, yani bildiğiniz TObject'ten türetilmiş bir sınıf...
  strict private                                  // Nesne dışından erişilemeyecek olan unsurlarımızı bu bölgede tanımlıyoruz
    constructor Create;                           // Böylece Kod yazarlarının bunları doğrudan kullanmalarını engellemiş oluyoruz.
    class var FInstance: TSingletonOrnegi;        // Nesne dışından erişilemeyen bu sınıf değişkeni, bizim, nesnenin "Tekilliğini" sağlamamıza yarayacak.
  public                                          // Herkese açık, ortaklaşa kullanılabilecek unsurlarımızı da bu bölgede tanımlıyoruz...
    class function GetInstance: TSingletonOrnegi; // Nesne "yoksa" üretir, "varsa" mevcut nesneye erişir...
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Tek  : TSingletonOrnegi;

implementation

{$R *.dfm}

{ TSingleton }

constructor TSingletonOrnegi.Create;
begin
  // Bu oluşturucu, "Strict Private" bölümünde tanımalndığı için dışarıdan doğrudan kullanılamaz.
  // Dolayısıyla doğrudan çağırılsa bile herhangi bir tepki vermeyecektir.
  inherited Create;

  { BU NOKTADA KOD YAZARLARINA GETINSTANCE METODUNU KULLANMALARI YÖNÜNDE BİR HATIRLATMA YAPMAK GEREKEBİLİR...}

  // Bunu test etmeniz amacıyla ekledim, silebilirsiniz.
  ShowMessage('OnCreate');
end;

class function TSingletonOrnegi.GetInstance: TSingletonOrnegi;
begin
  // Makalemizin can alıcı yordamı aslında burası, devam eden satırlarda bu nesnenin bir örneğinin oluş olmadığı sorgulanıyor
  // Yoksa hemen bir adet üretiliyor.
  // Varsa herhangi bir üretim söz konusu değil.
  if (FInstance = nil) then FInstance := TSingletonOrnegi.Create();

  // Sonrasında da sonuç değeri olarak örneğin kendisini dışarı veriyor...
  Result := FInstance;

  // Bunu da test etmeniz amacıyla ekledim, silebilirsiniz.
  ShowMessage('OnInstance');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // Doğru kullanımı bu şekilde...
  Tek := TSingletonOrnegi.GetInstance;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  VeyaBirBaskasi: TSingletonOrnegi;
begin
  // Aslında oluşturmayacak ve hiç bir tepki vermeyecek...
  Tek := TSingletonOrnegi.Create;

  // Bunu da oluşturmayacak ve yine tepki vermeyecek. Deneyin...
  VeyaBirBaskasi := TSingletonOrnegi.Create;
end;

end.

Bu olayı bir de görsel olarak incelemek gerekirse aşağıdaki animasyon sanırım iş görür...

ZO7orA.gif
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
WWW
Cevapla
#2
Teşekkürler yeni bir şey öğrenmiş oldum.
Cevapla
#3
Merhaba,
Yakın bir zamanda geliştirdiğim bir uygulamada, belirttiğiniz şekilde bir defaya mahsus oluşturulmak üzere bir sınıf kullanıyorum. Kendi kontrolümde olduğundan şuan için bir sorun olmuyor. Fakat sizin de vurguladığınız gibi; ileriye yönelik farklı kişiler tarafından geliştirebilme ihtimaline karşın, bu tedbir iyi olacaktır.
Paylaşımınız ve katkılarınızdan dolayı teşekkür ederim.
Cevapla
#4
(08-10-2017, Saat: 04:30)uparlayan Adlı Kullanıcıdan Alıntı: Hiç projenizin tamamında "şu nesneden sadece 1 tane üretilebilsin, başka da üretilemesin" dediğiniz anlar oldu mu? 

Problem

Proje büyüdükçe yönetilmesi gereken nesnelerin sayısı da çoğalıyor. Haliyle bu durum bazen karmaşaya da sebep olabiliyor. Fakat bazende öyle durumlar oluyor ki nesne sayısı çok olmasa bile bazı nesnelerin sadece bir kere üretilmesi işi çözüyor. 

Projede tek başınızayken bu tarz nesneleri idare etmek nispeten kolaydır, zira kaynak koda hakimsinizdir. Sonuçta birden fazla kez oluşturmazsınız olur biter... Peki, durum öyle değilse, yani unutursanız, veya projeye başkaları dahil olduysa o zaman ne yapılacak? İzlenecek yol belli değilse zamanla kaynak koddaki zarafetin yavaş yavaş yerini kaosa bıraktığı görülür...

Çözüm

Bu tarz, sadece bir kere oluşturulması gereken bazı nesneleriniz için Singleton Desenini kullanmak yeterli... Örnek vermek gerekirse, ben bazı projelerimde o projenin kişiliğini oluşturan belli başlı değişken gruplarını tek bir nesnede toplar ve o nesne üzerinden içeride projeyi yönetirim. Misal, kullanıcının oturum bilgileri veya o an hangi firma bilgileriyle çalışıldığını tutmak gibi örnekler verilebilir. Siz de bu tarz bir şeye ihtiyaç duyuyorsanız bu tasarım örneğini kullanmanızı tavsiye ederim.

Nasıl?

Singleton tipi bir nesne tanımı yapmanın sıradan bir sınıf tanımı yapmaktan pek bir farkı yoktur. Fark, özünde Create yerine GetInstance kullanılmasını sağlamaktadır. Nesneyi doğrudan Create etmeye kapatmak, ve bunun doğuracağı boşluğu da bu işlevi (yani Create'i) ikame edecek şekilde bir GetInstance fonksiyonu yazmaktır. 

Örnek

type
  TSingletonOrnegi = class                        // Bilinen şekilde sade, basit bir sınıf tanımı, yani hepimizin bildiği TObject'ten türetilmiş bir sınıf...
  strict private                                  // Nesne dışından erişilemeyecek olan unsurlarımızı bu bölgede tanımlıyoruz
    constructor Create;                           // Böylece Kod yazarlarının bunları doğrudan kullanmalarını engellemiş oluyoruz.
    class var FInstance: TSingletonOrnegi;        // Nesne dışından erişilemeyen bu sınıf değişkeni, bizim, nesnenin "Tekilliğini" sağlamamıza yarayacak.
  public                                          // Herkese açık, ortaklaşa kullanılabilecek unsurlarımızı da bu bölgede tanımlıyoruz...
    class function GetInstance: TSingletonOrnegi; // Nesne "yoksa" üretir, "varsa" mevcut nesneye erişir... Bu fonksiyonun veri tipi sınıfın kendisidir...
  end;

implementation

{$R *.dfm}

{ TSingleton }

constructor TSingletonOrnegi.Create;
begin
  // Bu oluşturucu, "Strict Private" bölümünde tanımalndığı için dışarıdan doğrudan kullanılamaz.
  // Dolayısıyla doğrudan çağırılsa bile herhangi bir tepki vermeyecektir.
  inherited Create;

  { BU NOKTADA KOD YAZARLARINA GETINSTANCE METODUNU KULLANMALARI YÖNÜNDE BİR HATIRLATMA YAPMAK GEREKEBİLİR...}

  // Bunu test etmeniz amacıyla ekledim, silebilirsiniz.
  ShowMessage('OnCreate');
end;

class function TSingletonOrnegi.GetInstance: TSingletonOrnegi;
begin
  // Makalemizin can alıcı yordamı aslında burası, devam eden satırlarda bu nesnenin bir örneğinin oluş olmadığı sorgulanıyor
  // Yoksa hemen bir adet üretiliyor.
  // Varsa herhangi bir üretim söz konusu değil.
  if (FInstance = nil)
  or (Assigned(FInstance) = False)
   then FInstance := TSingletonOrnegi.Create();

  // Sonrasında da sonuç değeri olarak örneğin kendisini dışarı veriyor...
  Result := FInstance;

  // Bunu da test etmeniz amacıyla ekledim, silebilirsiniz.
  ShowMessage('OnInstance');
end;

Ne Yaptık?

Görüldüğü gibi TSingletonOrnegi adlı nesnemizin constructoru olan Create yordamını Strict Private bölümüne taşıyarak dışarıdan erişime kapattık. Artık Create yordamı sadece nesnenin içerisindeki diğer metodlar tarafından ulaşılabilir hale geldi. Böylece Singleton sistematiğinin ilk adımını tamamlamış olduk. 

Singleton deseninin ikinci adımında ise Class Variable yapısını kullandık. Bildiğiniz üzere bir sınıf içerisindeki herhangi bir fonksiyon, prosedür, özellik, nitelik veya değişken tanımının başında class ibaresi getirilmişse bilinki nesnenin o kısmını nesneyi create etmeden, doğrudan kullanabilirsiniz. Bunu bir nevi sınıfın global bir değişkeni gibi düşünebilirsiniz... (Bunun mekaniğine bu makaleye yorum yazacak olan arkadaşlar mutlaka değinecektir diye düşünüyorum...)


Kaldığımız yerden devam edecek olursak; devamında da FInstance adlı TSingletonOrnegi tipinde bir sınıf değişkenini yine Strict Private bölümünde  tanımladık. Bu bölgede tanımlamamızın iki sebebi var. Birincisi nesne henüz ortada yokken bile biz bu nesnenin bir kopyası üretilmiş mi kontrol edebilelim. İkincisi ise bu değişkene dışarıdan müdahale olmasın, sadece sınıfın kendi içinden erişilebilsin...

Bu sayede biz, sınıfımızın çalışma esnasında bir örneğinin oluşturulup oluşturulmadığını kontrol edebilir hale gelmiş olduk. 

Son olarak, public bölümünde yine veri tipi TSingletonOrnegi olan bir Class Function tanımladık. Yukarıda belirttiğim mekanizma üzerinden nesnemizin daha önceden üretilip üretilmediğini sorgulayan, üretilmemişse de Strict Private bölümüne taşıdığımız Create oluşturucusunu çalıştıran bir fonksiyonla tasarımımızı tamamlamış olduk.

Kullanımı

Kısa cevap aşağıdaki gibi

Tek := TSingletonOrnegi.GetInstance;

Uzun cevap ise şöyle;

Şimdi bu örneğin nasıl kullanıldığını inceleyelim. Bunun için ben boş bir VCL Projesi oluşturup formun üzerine 2 adet TButton ve bir adet TMemo nesnesi ekledim. İlk butona bu örneğin normalde nasıl kullanılması gerektiği ile ilgili bir kod yazdım. İkincisine ise normalde bir sınıfı oluştururken hangi yolu izliyorsak onu yazdım. Anlatım bütünlüğünü bozmamak adına kaynak kodun tamamını aşağıya ekledim ve kaynak koda bazı açıklamalar ekledim.

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TSingletonOrnegi = class                        // Bilinen şekilde sade, basit bir sınıf tanımı, yani bildiğiniz TObject'ten türetilmiş bir sınıf...
  strict private                                  // Nesne dışından erişilemeyecek olan unsurlarımızı bu bölgede tanımlıyoruz
    constructor Create;                           // Böylece Kod yazarlarının bunları doğrudan kullanmalarını engellemiş oluyoruz.
    class var FInstance: TSingletonOrnegi;        // Nesne dışından erişilemeyen bu sınıf değişkeni, bizim, nesnenin "Tekilliğini" sağlamamıza yarayacak.
  public                                          // Herkese açık, ortaklaşa kullanılabilecek unsurlarımızı da bu bölgede tanımlıyoruz...
    class function GetInstance: TSingletonOrnegi; // Nesne "yoksa" üretir, "varsa" mevcut nesneye erişir...
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  Tek  : TSingletonOrnegi;

implementation

{$R *.dfm}

{ TSingleton }

constructor TSingletonOrnegi.Create;
begin
  // Bu oluşturucu, "Strict Private" bölümünde tanımalndığı için dışarıdan doğrudan kullanılamaz.
  // Dolayısıyla doğrudan çağırılsa bile herhangi bir tepki vermeyecektir.
  inherited Create;

  { BU NOKTADA KOD YAZARLARINA GETINSTANCE METODUNU KULLANMALARI YÖNÜNDE BİR HATIRLATMA YAPMAK GEREKEBİLİR...}

  // Bunu test etmeniz amacıyla ekledim, silebilirsiniz.
  ShowMessage('OnCreate');
end;

class function TSingletonOrnegi.GetInstance: TSingletonOrnegi;
begin
  // Makalemizin can alıcı yordamı aslında burası, devam eden satırlarda bu nesnenin bir örneğinin oluş olmadığı sorgulanıyor
  // Yoksa hemen bir adet üretiliyor.
  // Varsa herhangi bir üretim söz konusu değil.
  if (FInstance = nil) or (Assigned(FInstance) = False) then FInstance := TSingletonOrnegi.Create();

  // Sonrasında da sonuç değeri olarak örneğin kendisini dışarı veriyor...
  Result := FInstance;

  // Bunu da test etmeniz amacıyla ekledim, silebilirsiniz.
  ShowMessage('OnInstance');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // Doğru kullanımı bu şekilde...
  Tek := TSingletonOrnegi.GetInstance;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  VeyaBirBaskasi: TSingletonOrnegi;
begin
  // Aslında oluşturmayacak ve hiç bir tepki vermeyecek...
  Tek := TSingletonOrnegi.Create;

  // Bunu da oluşturmayacak ve yine tepki vermeyecek. Deneyin...
  VeyaBirBaskasi := TSingletonOrnegi.Create;
end;

end.

Bu olayı bir de görsel olarak incelemek gerekirse aşağıdaki animasyon sanırım iş görür...

ZO7orA.gif

 Katkılarınızdan dolayı teşekkürler üstad. Farklı bir açıyla aslında program bellek kullanımlarını, hızı gibi bir çok avantajları dezavantaja çeviren, bilinçsizce oluşturmuş olduğumuz bileşenlere de bir engel getirmiş oldu. 

Teşekkürler.
kisisel_logo_dark.png
WWW
Cevapla
#5
Burada da okuyabilirsiniz değişik örnekler üzerinde gitsek kutuphanemize genişler

Buradan Bakınız
Cevapla
#6
Bana bu yapı Thread Safety gelmedi. Sanırım Tuğrul hocamın kendi sayfasında yazdığı Critical Section benzeri bir yapı ile GetInstance metodundaki aşağıdaki kısmı güvence altına almak gerekir.

if (FInstance = nil) or (Assigned(FInstance) = False) then 
   FInstance := TSingletonOrnegi.Create();

// Sonrasında da sonuç değeri olarak örneğin kendisini dışarı veriyor...
Result := FInstance;

http://www.tugrulhelvaci.com/?p=443
Cevapla
#7
(09-10-2017, Saat: 13:26)edo Adlı Kullanıcıdan Alıntı: Bana bu yapı Thread Safety gelmedi. Sanırım Tuğrul hocamın kendi sayfasında yazdığı Critical Section benzeri bir yapı ile GetInstance metodundaki aşağıdaki kısmı güvence altına almak gerekir.

if (FInstance = nil) or (Assigned(FInstance) = False) then 
   FInstance := TSingletonOrnegi.Create();

// Sonrasında da sonuç değeri olarak örneğin kendisini dışarı veriyor...
Result := FInstance;

http://www.tugrulhelvaci.com/?p=443

Ufak bir hatırlatma yapayım, makalenin ilk cümlesi "Hiç projenizin tamamında 'şu nesneden sadece 1 tane üretilebilsin, başka da üretilemesin' dediğiniz anlar oldu mu? " şeklinde Wink

İşin içine Thread'ler girdiği zaman yukarıdaki önermenin zaten dışına çıkmış oluyoruz, o zaman da bir Singleton Deseninden bahsetmek mümkün değil.
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
WWW
Cevapla
#8
(09-10-2017, Saat: 14:31)uparlayan Adlı Kullanıcıdan Alıntı:
(09-10-2017, Saat: 13:26)edo Adlı Kullanıcıdan Alıntı: Bana bu yapı Thread Safety gelmedi. Sanırım Tuğrul hocamın kendi sayfasında yazdığı Critical Section benzeri bir yapı ile GetInstance metodundaki aşağıdaki kısmı güvence altına almak gerekir.

if (FInstance = nil) or (Assigned(FInstance) = False) then 
   FInstance := TSingletonOrnegi.Create();

// Sonrasında da sonuç değeri olarak örneğin kendisini dışarı veriyor...
Result := FInstance;

http://www.tugrulhelvaci.com/?p=443

Ufak bir hatırlatma yapayım, makalenin ilk cümlesi "Hiç projenizin tamamında 'şu nesneden sadece 1 tane üretilebilsin, başka da üretilemesin' dediğiniz anlar oldu mu? " şeklinde Wink

İşin içine Thread'ler girdiği zaman yukarıdaki önermenin zaten dışına çıkmış oluyoruz, o zaman da bir Singleton Deseninden bahsetmek mümkün değil.

Thread kullanılmayan bir proje demiyorsunuz, projede thread kullanıyorsak Singleton'dan niye bahsedemeyelim anlamadım  Angel
Cevapla
#9
Ben görüşünüzü bir thread'in içerisinde tekil bir nesne yaratmak istediğiniz şeklinde algıladım. Ana thread içinde oluşturulmuş tekil bir nesneye tabii ki ayrı threadler üzerinden de erişebilirsiniz. Bunda bir sakınca yok. Kaldı ki, bir thread içinde de singleton bir nesne üretebilirsiniz ama aynı thread'in birden çok kopyasını çalıştırmak istediğinizde bununla ilgili önlemler elbette almanız gerekir.
YouTube Delphi Tips
"Yaşlanarak değil, yaşayarak tecrübe kazanılır. Zaman insanları değil, armutları olgunlaştırır" Peyami Safa
WWW
Cevapla
#10
Thread içinden GetInstance metodu çağrıldığında birden fazla Instance oluşmaması için yani Pattern'in Thread Safety olarak kullanılabilmesi için böyle bir şeye gerek olduğunu hatırlatmak istemiştim.

Yazınız için teşekkürler bu arada, eminim faydalı olacaktır.
Cevapla


Konu ile Alakalı Benzer Konular
Konular Yazar Yorumlar Okunma Son Yorum
  Tasarım Desenleri : Fluent Design uparlayan 19 12.078 17-08-2020, Saat: 18:15
Son Yorum: uparlayan
  Tasarım Desenleri : Observer Design Pattern 2 uparlayan 4 2.459 08-08-2020, Saat: 10:43
Son Yorum: Bay_Y
  Tasarım Desenleri : Model View Controller uparlayan 7 4.149 22-07-2020, Saat: 10:25
Son Yorum: uparlayan
  Tasarım Desenleri : Model View Presenter uparlayan 1 1.628 13-07-2020, Saat: 09:29
Son Yorum: Bay_Y
  Tasarım Desenleri : Model-View-ModelView Supervision Controller Kip uparlayan 1 1.789 05-07-2020, Saat: 12:55
Son Yorum: Halil Han BADEM



Konuyu Okuyanlar: 1 Ziyaretçi