{"id":173,"date":"2019-09-30T22:25:39","date_gmt":"2019-09-30T19:25:39","guid":{"rendered":"http:\/\/www.potansif.com\/?p=173"},"modified":"2019-10-01T16:26:55","modified_gmt":"2019-10-01T13:26:55","slug":"tasarim-desenleri-singleton-design","status":"publish","type":"post","link":"http:\/\/www.potansif.com\/?p=173","title":{"rendered":"Tasar\u0131m Desenleri : Singleton Design"},"content":{"rendered":"<p>Hi\u00e7 projenizin tamam\u0131nda &#8220;\u015fu nesneden sadece 1 tane \u00fcretilebilsin, ba\u015fka da \u00fcretilemesin&#8221; dedi\u011finiz anlar oldu mu?<!--more--><\/p>\n<p><b>Problem<\/b><\/p>\n<p>Proje b\u00fcy\u00fcd\u00fck\u00e7e y\u00f6netilmesi gereken nesnelerin&nbsp;say\u0131s\u0131 da&nbsp;\u00e7o\u011fal\u0131yor. Haliyle bu durum bazen karma\u015faya da sebep olabiliyor. Fakat bazende \u00f6yle durumlar oluyor ki nesne say\u0131s\u0131 \u00e7ok olmasa bile baz\u0131 nesnelerin sadece bir kere \u00fcretilmesi i\u015fi \u00e7\u00f6z\u00fcyor.&nbsp;<\/p>\n<p>Projede tek ba\u015f\u0131n\u0131zayken bu tarz nesneleri&nbsp;idare etmek nispeten kolayd\u0131r, zira kaynak koda hakimsinizdir. Sonu\u00e7ta birden fazla kez olu\u015fturmazs\u0131n\u0131z olur biter&#8230; Peki, durum \u00f6yle de\u011filse, yani&nbsp;unutursan\u0131z,&nbsp;veya projeye ba\u015fkalar\u0131&nbsp;dahil olduysa&nbsp;o zaman ne yap\u0131lacak? \u0130zlenecek yol belli de\u011filse zamanla kaynak koddaki zarafetin yava\u015f yava\u015f yerini kaosa b\u0131rakt\u0131\u011f\u0131 g\u00f6r\u00fcl\u00fcr&#8230;<\/p>\n<p><b>\u00c7\u00f6z\u00fcm<\/b><\/p>\n<p>Bu tarz, sadece bir kere olu\u015fturulmas\u0131 gereken baz\u0131 nesneleriniz i\u00e7in Singleton Desenini kullanmak yeterli&#8230; \u00d6rnek vermek gerekirse, ben baz\u0131 projelerimde o projenin ki\u015fili\u011fini olu\u015fturan belli ba\u015fl\u0131 de\u011fi\u015fken gruplar\u0131n\u0131 tek bir nesnede toplar ve o nesne \u00fczerinden i\u00e7eride projeyi y\u00f6netirim. Misal, kullan\u0131c\u0131n\u0131n oturum bilgileri veya o an hangi firma bilgileriyle \u00e7al\u0131\u015f\u0131ld\u0131\u011f\u0131n\u0131 tutmak gibi \u00f6rnekler verilebilir. Siz de bu tarz bir \u015feye ihtiya\u00e7 duyuyorsan\u0131z bu tasar\u0131m \u00f6rne\u011fini kullanman\u0131z\u0131 tavsiye ederim.<\/p>\n<p><b>Nas\u0131l?<\/b><\/p>\n<p>Singleton tipi bir nesne tan\u0131m\u0131&nbsp;yapman\u0131n s\u0131radan bir s\u0131n\u0131f tan\u0131m\u0131 yapmaktan pek bir fark\u0131 yoktur. Fark, \u00f6z\u00fcnde Create yerine GetInstance kullan\u0131lmas\u0131n\u0131 sa\u011flamaktad\u0131r.&nbsp;Nesneyi do\u011frudan Create etmeye kapatmak, ve bunun do\u011furaca\u011f\u0131 bo\u015flu\u011fu da bu i\u015flevi (yani&nbsp;Create&#8217;i) ikame edecek \u015fekilde bir GetInstance fonksiyonu yazmakt\u0131r.&nbsp;<\/p>\n<p><b>\u00d6rnek<\/b><\/p>\n<pre><code>type\r\n&nbsp; TSingletonOrnegi = class&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Bilinen \u015fekilde sade, basit bir s\u0131n\u0131f tan\u0131m\u0131, yani hepimizin bildi\u011fi TObject'ten t\u00fcretilmi\u015f bir s\u0131n\u0131f...\r\n&nbsp; strict private&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Nesne d\u0131\u015f\u0131ndan eri\u015filemeyecek olan unsurlar\u0131m\u0131z\u0131 bu b\u00f6lgede tan\u0131ml\u0131yoruz\r\n&nbsp; &nbsp; constructor Create;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ B\u00f6ylece Kod yazarlar\u0131n\u0131n bunlar\u0131 do\u011frudan kullanmalar\u0131n\u0131 engellemi\u015f oluyoruz.\r\n&nbsp; &nbsp; class var FInstance: TSingletonOrnegi;&nbsp; &nbsp; &nbsp; &nbsp; \/\/ Nesne d\u0131\u015f\u0131ndan eri\u015filemeyen bu s\u0131n\u0131f de\u011fi\u015fkeni, bizim, nesnenin \"Tekilli\u011fini\" sa\u011flamam\u0131za yarayacak.\r\n&nbsp; public&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Herkese a\u00e7\u0131k, ortakla\u015fa kullan\u0131labilecek unsurlar\u0131m\u0131z\u0131 da bu b\u00f6lgede tan\u0131ml\u0131yoruz...\r\n&nbsp; &nbsp; class function GetInstance: TSingletonOrnegi; \/\/ Nesne \"yoksa\" \u00fcretir, \"varsa\" mevcut nesneye eri\u015fir... Bu fonksiyonun veri tipi s\u0131n\u0131f\u0131n kendisidir...\r\n&nbsp; end;\r\n\r\nimplementation\r\n\r\n{$R *.dfm}\r\n\r\n{ TSingleton }\r\n\r\nconstructor TSingletonOrnegi.Create;\r\nbegin\r\n&nbsp; \/\/ Bu olu\u015fturucu, \"Strict Private\" b\u00f6l\u00fcm\u00fcnde tan\u0131malnd\u0131\u011f\u0131 i\u00e7in d\u0131\u015far\u0131dan do\u011frudan kullan\u0131lamaz.\r\n&nbsp; \/\/ Dolay\u0131s\u0131yla do\u011frudan \u00e7a\u011f\u0131r\u0131lsa bile herhangi bir tepki vermeyecektir.\r\n&nbsp; inherited Create;\r\n\r\n&nbsp; { BU NOKTADA KOD YAZARLARINA&nbsp;GETINSTANCE METODUNU KULLANMALARI Y\u00d6N\u00dcNDE&nbsp;B\u0130R HATIRLATMA YAPMAK GEREKEB\u0130L\u0130R...}\r\n\r\n&nbsp; \/\/ Bunu test etmeniz amac\u0131yla ekledim, silebilirsiniz.\r\n&nbsp; ShowMessage('OnCreate');\r\nend;\r\n\r\nclass function TSingletonOrnegi.GetInstance: TSingletonOrnegi;\r\nbegin\r\n&nbsp; \/\/ Makalemizin can al\u0131c\u0131 yordam\u0131 asl\u0131nda buras\u0131, devam eden sat\u0131rlarda bu nesnenin bir \u00f6rne\u011finin olu\u015f olmad\u0131\u011f\u0131 sorgulan\u0131yor\r\n&nbsp; \/\/ Yoksa hemen bir adet \u00fcretiliyor.\r\n&nbsp; \/\/ Varsa herhangi bir \u00fcretim s\u00f6z konusu de\u011fil.\r\n&nbsp; if (FInstance = nil) then FInstance := TSingletonOrnegi.Create();\r\n\r\n&nbsp; \/\/ Sonras\u0131nda da sonu\u00e7 de\u011feri olarak \u00f6rne\u011fin kendisini d\u0131\u015far\u0131 veriyor...\r\n&nbsp; Result := FInstance;\r\n\r\n&nbsp; \/\/ Bunu da test etmeniz amac\u0131yla ekledim, silebilirsiniz.\r\n&nbsp; ShowMessage('OnInstance');\r\nend;<\/code><\/pre>\n<p><b>Ne Yapt\u0131k?<\/b><\/p>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc gibi TSingletonOrnegi adl\u0131 nesnemizin constructoru olan <b>Create <\/b>yordam\u0131n\u0131 <b>Strict Private<\/b> b\u00f6l\u00fcm\u00fcne ta\u015f\u0131yarak d\u0131\u015far\u0131dan eri\u015fime kapatt\u0131k. Art\u0131k Create yordam\u0131 sadece nesnenin i\u00e7erisindeki di\u011fer metodlar taraf\u0131ndan&nbsp;ula\u015f\u0131labilir hale geldi. B\u00f6ylece Singleton sistemati\u011finin ilk ad\u0131m\u0131n\u0131 tamamlam\u0131\u015f olduk.&nbsp;<\/p>\n<p>Singleton deseninin ikinci ad\u0131m\u0131nda ise Class Variable yap\u0131s\u0131n\u0131 kulland\u0131k. Bildi\u011finiz \u00fczere bir s\u0131n\u0131f i\u00e7erisindeki herhangi&nbsp;bir fonksiyon, prosed\u00fcr, \u00f6zellik, nitelik&nbsp;veya de\u011fi\u015fken&nbsp;tan\u0131m\u0131n\u0131n ba\u015f\u0131nda <b>class<\/b> ibaresi&nbsp;getirilmi\u015fse bilinki nesnenin o k\u0131sm\u0131n\u0131 nesneyi create etmeden, do\u011frudan kullanabilirsiniz. Bunu bir nevi s\u0131n\u0131f\u0131n global bir de\u011fi\u015fkeni gibi d\u00fc\u015f\u00fcnebilirsiniz&#8230;&nbsp;(<i><u>Bunun mekani\u011fine bu makaleye yorum yazacak olan arkada\u015flar mutlaka de\u011finecektir diye d\u00fc\u015f\u00fcn\u00fcyorum&#8230;<\/u><\/i>)<\/p>\n<p>Kald\u0131\u011f\u0131m\u0131z yerden devam edecek olursak; devam\u0131nda da <b>FInstance <\/b>adl\u0131 <b>TSingletonOrnegi <\/b>tipinde bir s\u0131n\u0131f de\u011fi\u015fkenini yine <b>Strict Private<\/b> b\u00f6l\u00fcm\u00fcnde&nbsp; tan\u0131mlad\u0131k. Bu b\u00f6lgede tan\u0131mlamam\u0131z\u0131n iki&nbsp;sebebi var. Birincisi nesne hen\u00fcz ortada yokken bile biz bu nesnenin bir kopyas\u0131 \u00fcretilmi\u015f mi kontrol edebilelim. \u0130kincisi ise bu de\u011fi\u015fkene d\u0131\u015far\u0131dan m\u00fcdahale olmas\u0131n, sadece s\u0131n\u0131f\u0131n kendi i\u00e7inden eri\u015filebilsin&#8230;<\/p>\n<p>Bu sayede biz, s\u0131n\u0131f\u0131m\u0131z\u0131n \u00e7al\u0131\u015fma esnas\u0131nda bir \u00f6rne\u011finin olu\u015fturulup olu\u015fturulmad\u0131\u011f\u0131n\u0131 kontrol edebilir hale gelmi\u015f olduk.&nbsp;<\/p>\n<p>Son olarak, <b>public <\/b>b\u00f6l\u00fcm\u00fcnde yine veri tipi <b>TSingletonOrnegi <\/b>olan&nbsp;bir <b>Class Function<\/b>&nbsp;tan\u0131mlad\u0131k. Yukar\u0131da belirtti\u011fim mekanizma \u00fczerinden nesnemizin daha \u00f6nceden \u00fcretilip \u00fcretilmedi\u011fini sorgulayan, \u00fcretilmemi\u015fse de Strict Private b\u00f6l\u00fcm\u00fcne ta\u015f\u0131d\u0131\u011f\u0131m\u0131z Create olu\u015fturucusunu \u00e7al\u0131\u015ft\u0131ran bir fonksiyonla tasar\u0131m\u0131m\u0131z\u0131 tamamlam\u0131\u015f olduk.<\/p>\n<p><b>Kullan\u0131m\u0131<\/b><\/p>\n<p><i>K\u0131sa cevap a\u015fa\u011f\u0131daki gibi<\/i><\/p>\n<pre><code>Tek := TSingletonOrnegi.GetInstance;<\/code><\/pre>\n<p><i>Uzun cevap ise \u015f\u00f6yle;<\/i><\/p>\n<p>\u015eimdi bu \u00f6rne\u011fin nas\u0131l kullan\u0131ld\u0131\u011f\u0131n\u0131 inceleyelim. Bunun i\u00e7in ben bo\u015f bir VCL Projesi olu\u015fturup formun \u00fczerine 2 adet TButton ve bir adet TMemo nesnesi ekledim. \u0130lk butona bu \u00f6rne\u011fin normalde nas\u0131l kullan\u0131lmas\u0131 gerekti\u011fi ile ilgili bir kod yazd\u0131m. \u0130kincisine ise normalde bir s\u0131n\u0131f\u0131 olu\u015ftururken hangi yolu izliyorsak onu yazd\u0131m. Anlat\u0131m b\u00fct\u00fcnl\u00fc\u011f\u00fcn\u00fc bozmamak ad\u0131na kaynak kodun tamam\u0131n\u0131 a\u015fa\u011f\u0131ya ekledim ve kaynak koda baz\u0131 a\u00e7\u0131klamalar ekledim.<\/p>\n<pre><code>unit Unit1;\r\n\r\ninterface\r\n\r\nuses\r\n&nbsp; Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,\r\n&nbsp; Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;\r\n\r\ntype\r\n&nbsp; TSingletonOrnegi = class&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Bilinen \u015fekilde sade, basit bir s\u0131n\u0131f tan\u0131m\u0131, yani bildi\u011finiz TObject'ten t\u00fcretilmi\u015f bir s\u0131n\u0131f...\r\n&nbsp; strict private&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Nesne d\u0131\u015f\u0131ndan eri\u015filemeyecek olan unsurlar\u0131m\u0131z\u0131 bu b\u00f6lgede tan\u0131ml\u0131yoruz\r\n&nbsp; &nbsp; constructor Create;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ B\u00f6ylece Kod yazarlar\u0131n\u0131n bunlar\u0131 do\u011frudan kullanmalar\u0131n\u0131 engellemi\u015f oluyoruz.\r\n&nbsp; &nbsp; class var FInstance: TSingletonOrnegi;&nbsp; &nbsp; &nbsp; &nbsp; \/\/ Nesne d\u0131\u015f\u0131ndan eri\u015filemeyen bu s\u0131n\u0131f de\u011fi\u015fkeni, bizim, nesnenin \"Tekilli\u011fini\" sa\u011flamam\u0131za yarayacak.\r\n&nbsp; public&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Herkese a\u00e7\u0131k, ortakla\u015fa kullan\u0131labilecek unsurlar\u0131m\u0131z\u0131 da bu b\u00f6lgede tan\u0131ml\u0131yoruz...\r\n&nbsp; &nbsp; class function GetInstance: TSingletonOrnegi; \/\/ Nesne \"yoksa\" \u00fcretir, \"varsa\" mevcut nesneye eri\u015fir...\r\n&nbsp; end;\r\n\r\n&nbsp; TForm1 = class(TForm)\r\n&nbsp; &nbsp; Button1: TButton;\r\n&nbsp; &nbsp; Button2: TButton;\r\n&nbsp; &nbsp; Memo1: TMemo;\r\n&nbsp; &nbsp; Button3: TButton;\r\n&nbsp; &nbsp; procedure Button1Click(Sender: TObject);\r\n&nbsp; &nbsp; procedure Button2Click(Sender: TObject);\r\n&nbsp; private\r\n&nbsp; &nbsp; { Private declarations }\r\n&nbsp; public\r\n&nbsp; &nbsp; { Public declarations }\r\n&nbsp; end;\r\n\r\nvar\r\n&nbsp; Form1: TForm1;\r\n&nbsp; Tek&nbsp; : TSingletonOrnegi;\r\n\r\nimplementation\r\n\r\n{$R *.dfm}\r\n\r\n{ TSingleton }\r\n\r\nconstructor TSingletonOrnegi.Create;\r\nbegin\r\n&nbsp; \/\/ Bu olu\u015fturucu, \"Strict Private\" b\u00f6l\u00fcm\u00fcnde tan\u0131malnd\u0131\u011f\u0131 i\u00e7in d\u0131\u015far\u0131dan do\u011frudan kullan\u0131lamaz.\r\n&nbsp; \/\/ Dolay\u0131s\u0131yla do\u011frudan \u00e7a\u011f\u0131r\u0131lsa bile herhangi bir tepki vermeyecektir.\r\n&nbsp; inherited Create;\r\n\r\n&nbsp; { BU NOKTADA KOD YAZARLARINA&nbsp;GETINSTANCE METODUNU KULLANMALARI Y\u00d6N\u00dcNDE&nbsp;B\u0130R HATIRLATMA YAPMAK GEREKEB\u0130L\u0130R...}\r\n\r\n&nbsp; \/\/ Bunu test etmeniz amac\u0131yla ekledim, silebilirsiniz.\r\n&nbsp; ShowMessage('OnCreate');\r\nend;\r\n\r\nclass function TSingletonOrnegi.GetInstance: TSingletonOrnegi;\r\nbegin\r\n&nbsp; \/\/ Makalemizin can al\u0131c\u0131 yordam\u0131 asl\u0131nda buras\u0131, devam eden sat\u0131rlarda bu nesnenin bir \u00f6rne\u011finin olu\u015f olmad\u0131\u011f\u0131 sorgulan\u0131yor\r\n&nbsp; \/\/ Yoksa hemen bir adet \u00fcretiliyor.\r\n&nbsp; \/\/ Varsa herhangi bir \u00fcretim s\u00f6z konusu de\u011fil.\r\n&nbsp; if (FInstance = nil) then FInstance := TSingletonOrnegi.Create();\r\n\r\n&nbsp; \/\/ Sonras\u0131nda da sonu\u00e7 de\u011feri olarak \u00f6rne\u011fin kendisini d\u0131\u015far\u0131 veriyor...\r\n&nbsp; Result := FInstance;\r\n\r\n&nbsp; \/\/ Bunu da test etmeniz amac\u0131yla ekledim, silebilirsiniz.\r\n&nbsp; ShowMessage('OnInstance');\r\nend;\r\n\r\nprocedure TForm1.Button1Click(Sender: TObject);\r\nbegin\r\n&nbsp; \/\/ Do\u011fru kullan\u0131m\u0131 bu \u015fekilde...\r\n&nbsp; Tek := TSingletonOrnegi.GetInstance;\r\nend;\r\n\r\nprocedure TForm1.Button2Click(Sender: TObject);\r\nvar\r\n&nbsp; VeyaBirBaskasi: TSingletonOrnegi;\r\nbegin\r\n&nbsp; \/\/ Asl\u0131nda olu\u015fturmayacak ve hi\u00e7 bir tepki vermeyecek...\r\n&nbsp; Tek := TSingletonOrnegi.Create;\r\n\r\n&nbsp; \/\/ Bunu da olu\u015fturmayacak ve yine tepki vermeyecek. Deneyin...\r\n&nbsp; VeyaBirBaskasi := TSingletonOrnegi.Create;\r\nend;\r\n\r\nend.<\/code><\/pre>\n<p>Bu olay\u0131 bir de g\u00f6rsel olarak incelemek gerekirse a\u015fa\u011f\u0131daki animasyon san\u0131r\u0131m i\u015f g\u00f6r\u00fcr&#8230;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/rubicube.com.tr\/wp-content\/uploads\/2018\/09\/ZO7orA1.gif\" alt=\"\" width=\"509\" height=\"299\" class=\"alignnone size-full wp-image-583\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hi\u00e7 projenizin tamam\u0131nda &#8220;\u015fu nesneden sadece 1 tane \u00fcretilebilsin, ba\u015fka da \u00fcretilemesin&#8221; dedi\u011finiz anlar oldu mu?<\/p>\n","protected":false},"author":1,"featured_media":263,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[4,35,38,36],"class_list":["post-173","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-delphi","tag-design-patterns","tag-singleton","tag-tasarim-desenleri"],"_links":{"self":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/173","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=173"}],"version-history":[{"count":1,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/173\/revisions"}],"predecessor-version":[{"id":180,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/173\/revisions\/180"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/media\/263"}],"wp:attachment":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=173"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=173"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=173"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}