{"id":172,"date":"2019-09-30T22:24:48","date_gmt":"2019-09-30T19:24:48","guid":{"rendered":"http:\/\/www.potansif.com\/?p=172"},"modified":"2019-10-01T17:30:57","modified_gmt":"2019-10-01T14:30:57","slug":"tasarim-desenleri-factory-method","status":"publish","type":"post","link":"http:\/\/www.potansif.com\/?p=172","title":{"rendered":"Tasar\u0131m Desenleri : Factory Method"},"content":{"rendered":"<p>Tamam\u0131n\u0131 elden ge\u00e7irmektense sadece tek bir parametreyi de\u011fi\u015ftirerek projenizin mevcut davran\u0131\u015f\u0131n\u0131 yeniden d\u00fczenlemek veya ek davran\u0131\u015flar geli\u015ftirmek istedi\u011finiz zamanlar oldu mu? &#8220;Biz zaten b\u00f6yle \u015feyler yapabiliyoruz&#8221; dedi\u011finizi duyar gibiyim&#8230; Kaz\u0131n aya\u011f\u0131 ger\u00e7ekten de \u00f6yle mi acaba? Bu konuda birileri kafa yormu\u015f&#8230;<!--more--><\/p>\n<p><b>Problem<\/b><\/p>\n<p>B\u00fcy\u00fck veya gere\u011finden fazla \u015fi\u015fmanlayan projelerin temel bir sorunu vard\u0131r: \u0130yi planlanmam\u0131\u015fsa zamanla dinamizmini kaybeder ve yava\u015f yava\u015f daha statik, daha hantal bir \u015fekle b\u00fcr\u00fcn\u00fcrler. Baz\u0131lar\u0131 i\u00e7in bu pekde \u00f6nemli bir konu olmayabilir fakat projeniz canl\u0131ysa ve yeni talepler gelmeye devam ediyorsa bu durum sizin i\u00e7in eziyet haline de d\u00f6n\u00fc\u015febilir.<\/p>\n<p>Diyelim ki, projenizde log tutmak i\u00e7in veritaban\u0131ndan faydalan\u0131yorsunuz ve i\u015fin en ba\u015f\u0131ndan beri loglama s\u00fcrecini b\u00f6yle planlam\u0131\u015fs\u0131n\u0131z ve uzun zamand\u0131rda bu i\u015f b\u00f6yle y\u00fcr\u00fcm\u00fc\u015f gitmi\u015f&#8230; E g\u00fczel, log tutulabilecek her noktada bununla ilgili big\u00fczel kodlar da yazm\u0131\u015fs\u0131n\u0131z&#8230; S\u0131k\u0131nt\u0131 yokmu\u015f gibi g\u00f6z\u00fck\u00fcyor de\u011filmi, \u00e7\u00fcnk\u00fc siz yap\u0131lmas\u0131 gereken her\u015feyi yapm\u0131\u015f ve i\u015fleri ray\u0131na oturtmu\u015fsunuz&#8230; Peki, tamam, g\u00fcn\u00fcn birinde m\u00fc\u015fterinin teki log bilgilerinin kendisine Eposta ile bildirilmesini istedi diyelim. Veya bir ba\u015fkas\u0131 \u00e7\u0131k\u0131p &#8220;bana bu log bilgileri SMS ile gelsin&#8221;, ya da ba\u015fka bir m\u00fc\u015fteri &#8220;veritaban\u0131m\u0131 loglarla doldurmak istemiyorum, onun yerine client&#8217;lerde text dosyada tutulsun&#8221; gibisinden taleplerde bulundu diyelim&#8230; Bu durumda Projenizde de\u011fi\u015ftirmek zorunda oldu\u011funuz bir davran\u0131\u015f i\u00e7in bir \u00e7ok noktay\u0131 elden ge\u00e7irmek zorunda kalabilece\u011finizin fark\u0131nda m\u0131s\u0131n\u0131z? Veya \u015f\u00f6yle s\u00f6yleyeyim; &#8220;Ya ne g\u00fczel, mutlu mesut loglar\u0131m\u0131 veritaban\u0131nda tutuyordum, nereden \u00e7\u0131kt\u0131 bu abuk subuk istekler&#8221; diye d\u00fc\u015f\u00fcnmeye ba\u015flad\u0131n\u0131z belki de&#8230; \u0130\u015fte problemin kendisi asl\u0131nda bu, yani koskoca projeyi tamamen elden ge\u00e7irmek ve her noktas\u0131na m\u00fcdahale etmek&#8230; Normalde \u00e7al\u0131\u015fan ana kodunuza m\u00fcdahale ediyorsan\u0131z bilin ki k\u00f6kten yanl\u0131\u015f bir \u015fey yap\u0131yorsunuz, \u00e7\u00fcnk\u00fc bunun bir bedeli var. Halbuki bunun basit bir \u00e7\u00f6z\u00fcm\u00fc olabilir&#8230;<\/p>\n<p><b>\u00c7\u00f6z\u00fcm<\/b><\/p>\n<p>Her\u015feyden \u00f6nce, bu tarz m\u00fc\u015fteri taleplerinin herzaman gelebilece\u011fini \u00f6nko\u015ful olarak zaten en ba\u015ftan kabul etmi\u015f olman\u0131z gerekiyor&#8230; O nedenle i\u015fin proje y\u00f6netimi k\u0131sm\u0131na zaten de\u011finmeyece\u011fim (ki konumuz da de\u011fil zaten) fakat teknik boyuta gelecek olursak; bu noktada literat\u00fcr bize &#8220;Factory Method&#8221; (Fabrika Y\u00f6ntemi) tekniklerini kullanmam\u0131z gerekti\u011fini \u00f6neriyor&#8230;<\/p>\n<p>Bu tasar\u0131m deseninin \u015f\u00f6yle bir tan\u0131m\u0131 var; &#8220;Factory Method modeli, S\u0131n\u0131f Tabanl\u0131 programlamada olu\u015fturulacak nesnenin, s\u0131n\u0131f\u0131n kendisini do\u011frudan belirtmek zorunda kalmadan, nesne olu\u015fturma sorunuyla ba\u015fa \u00e7\u0131kmak i\u00e7in, Factory Method zihniyetini kullanan bir \u00fcretim desenidir. Bu, bir arabirim taraf\u0131ndan \u00e7a\u011fr\u0131lan, bir arabirim taraf\u0131ndan belirtilen ve alt s\u0131n\u0131flar taraf\u0131ndan uyarlanan (implemente edilen) veya bir temel s\u0131n\u0131fta uygulanan ve istenirse t\u00fcretilmi\u015f s\u0131n\u0131flara g\u00f6re bir fabrika y\u00f6ntemini \u00e7a\u011f\u0131rarak, bir kurucu \u00e7a\u011f\u0131rmak yerine, nesneler olu\u015fturarak yap\u0131l\u0131r.&#8221; diyor&#8230;<\/p>\n<p>Yani biz bundan ne anl\u0131yoruz? \u00d6zetleyecek olursak; i\u015fi yapacak olan fiili, ger\u00e7ek nesneler ile i\u015fi talep edecek olan nesneler aras\u0131ndaki ba\u011flant\u0131y\u0131 soyut bir s\u0131n\u0131f veya (soyut) bir arabirim vass\u0131tas\u0131yla yap\u0131n. B\u00f6ylece t\u00fcr tipleri ve d\u00f6n\u00fc\u015f\u00fcmleri ile u\u011fra\u015fmaktan, bir \u00e7ok yerde IF bloklar\u0131 ile cebelle\u015fmekten kurtulun&#8230;<\/p>\n<p>Yani asl\u0131nda buradan da anla\u015f\u0131ld\u0131\u011f\u0131 \u00fczere Factory Method&#8217;un temel amac\u0131, de\u011fi\u015fkenlik g\u00f6sterebilecek, zamanla farkl\u0131 tekniklerin uyarlanabilmesini sa\u011flayabilecek bir yap\u0131y\u0131 bar\u0131nd\u0131rmas\u0131 nedeniyle yaz\u0131l\u0131mlar\u0131m\u0131zda, kodlamalar\u0131m\u0131zda de\u011fi\u015fimi kontrol alt\u0131na alabilmemizi sa\u011flamakt\u0131r.<\/p>\n<p><b>Nas\u0131l?<\/b><\/p>\n<p>Peki biz bunu nas\u0131l yapaca\u011f\u0131z? Kavram\u0131n kendisi soyut oldu\u011fu i\u00e7in somut bir \u00f6rnek \u00fczerinden bu konuyu anlatmak herhalde daha uygun ve kolay olacakt\u0131r. Yaz\u0131n\u0131n en ba\u015f\u0131ndaki \u00f6rnek \u00fczerinden ilerleyelim isterseniz. Konunun daha iyi anla\u015f\u0131labilmesi ad\u0131na tasar\u0131m desenindeki baz\u0131 nesleleri belli unit&#8217;lerde toparlad\u0131m, bu sayede tasar\u0131m desenini, i\u015f nesnelerinizi ve ana uygulaman\u0131z\u0131 birbirinden daha kolay ay\u0131rdedebilmenizi hedefledim.<\/p>\n<p>\u00d6nce arabirimlerimizi tan\u0131mlayal\u0131m;<\/p>\n<pre><code>\r\nunit FactoryPattern_Objects;\r\n\r\ninterface\r\n\r\nuses\r\n&nbsp;Vcl.Dialogs;\r\n\r\ntype\r\n&nbsp;{ Arabirimlerimizi tan\u0131ml\u0131yoruz }\r\n&nbsp;ILogcu = interface &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Bu bizim log tutmak i\u00e7in kullanaca\u011f\u0131m\u0131z TEMS\u0130L\u0130 bir arabirim ( Soyuttur kendileri... )\r\n&nbsp; &nbsp;&nbsp;procedure Log(const aLog: String); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Bu da bizim log tutmak i\u00e7in kullanaca\u011f\u0131m\u0131z yine TEMS\u0130L\u0130 bir METODUMUZ ( Bu da soyut... )\r\n&nbsp;end;\r\n&nbsp;ILogFabrikasi = interface &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ Bu bizim log fabrikas\u0131 \u00fcretmek i\u00e7in kulland\u0131\u011f\u0131m\u0131z TEMS\u0130L\u0130 bir arabirim ( Bu da soyut )\r\n&nbsp; &nbsp;function CreateLogcu: ILogcu; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ Bu da bizim FACTORY METHOD ile kastetti\u011fimiz fabrikam\u0131z... Olay asl\u0131nda bunu tan\u0131mlamakla ba\u015fl\u0131yor...\r\n&nbsp;end;\r\n\r\n&nbsp;{ LOGCU S\u0131n\u0131flar\u0131m\u0131z\u0131 tan\u0131ml\u0131yoruz }\r\n&nbsp;TLogcu_SQL = class(TInterfacedObject, ILogcu) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ Bu SQL ile log tutan \"GER\u00c7EK\" bir s\u0131n\u0131f \u00f6rne\u011fimiz, arabirimimizi implemente edece\u011fimiz ger\u00e7ek nesnelerden birisi bu olacak\r\n&nbsp; &nbsp;public\r\n&nbsp; &nbsp; &nbsp;procedure Log(const aLog: String); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Logu SQL'de tutacak olan \"GER\u00c7EK\" bir metod. Bunun i\u00e7inde fiilen SQL Scriptlerini \u00e7al\u0131\u015ft\u0131ran bir kod olmas\u0131 gerekecek...\r\n&nbsp;end;\r\n&nbsp;TLogcu_SMS = class(TInterfacedObject, ILogcu) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ Bu SMS ile log tutan \"GER\u00c7EK\" bir s\u0131n\u0131f \u00f6rne\u011fi, bunu da ILOGCU'dan t\u00fcrettik!\r\n&nbsp; &nbsp;public\r\n&nbsp; &nbsp; &nbsp;procedure Log(const aLog: String); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Logu SMS ile g\u00f6nderecek olan \"GER\u00c7EK\" bir metod. Bunun i\u00e7inde fiilen SMS g\u00f6nderen bir kod olmas\u0131 gerekecek...\r\n&nbsp;end;\r\n&nbsp;TLogcu_MAIL = class(TInterfacedObject, ILogcu) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Bu da EPOSTA ile log tutan yine \"GER\u00c7EK\" bir s\u0131n\u0131f \u00f6rne\u011fi, bunu da ILOGCU'dan t\u00fcrettik!\r\n&nbsp; &nbsp;public\r\n&nbsp; &nbsp; &nbsp;procedure Log(const aLog: String); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ Logu EPOSTA ile g\u00f6nderecek olan \"GER\u00c7EK\" bir metod. Bunun i\u00e7inde fiilen EPOSTA g\u00f6nderen bir kod olmas\u0131 gerekecek...\r\n&nbsp;end;\r\n\r\n&nbsp;{ FACTORY METHOD'lar\u0131m\u0131z\u0131 tutan s\u0131n\u0131flar\u0131 tan\u0131ml\u0131yoruz }\r\n&nbsp;TLogFabrikasi_SQL = class(TInterfacedObject, ILogFabrikasi) &nbsp;\/\/ SQL i\u00e7in kullanaca\u011f\u0131m\u0131z loglama s\u0131n\u0131f\u0131n\u0131 \u00fcretecek olan fabrika s\u0131n\u0131f\u0131m\u0131z\r\n&nbsp; &nbsp;public\r\n&nbsp; &nbsp; &nbsp;function CreateLogcu: ILogcu; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ FABR\u0130KA METODUMUZ, Danan\u0131n kuyru\u011funun koptu\u011fu yerlerden birisi buras\u0131\r\n&nbsp;end;\r\n&nbsp;TLogFabrikasi_SMS = class(TInterfacedObject, ILogFabrikasi) &nbsp;\/\/ SMS i\u00e7in kullanaca\u011f\u0131m\u0131z loglama s\u0131n\u0131f\u0131n\u0131 \u00fcretecek olan fabrika s\u0131n\u0131f\u0131m\u0131z\r\n&nbsp; &nbsp;public\r\n&nbsp; &nbsp; &nbsp;function CreateLogcu: ILogcu; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ FABR\u0130KA METODUMUZ, Danan\u0131n kuyru\u011funun koptu\u011fu yerlerden birisi de buras\u0131\r\n&nbsp;end;\r\n&nbsp;TLogFabrikasi_MAIL = class(TInterfacedObject, ILogFabrikasi) \/\/ EPOSTA i\u00e7in kullanaca\u011f\u0131m\u0131z loglama s\u0131n\u0131f\u0131n\u0131 \u00fcretecek olan fabrika s\u0131n\u0131f\u0131m\u0131z\r\n&nbsp; &nbsp;public\r\n&nbsp; &nbsp; &nbsp;function CreateLogcu: ILogcu; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ FABR\u0130KA METODUMUZ, Danan\u0131n kuyru\u011funun koptu\u011fu yerlerden birisi de buras\u0131\r\n&nbsp;end;\r\n\r\nimplementation\r\n\r\n{ TLogcu_SMS }\r\n\r\nprocedure TLogcu_SMS.Log(const aLog: String);\r\nbegin\r\n&nbsp;ShowMessage('SMS ile loglama yap\u0131ld\u0131: ' + aLog);\r\n&nbsp;\/\/ Burada SMS g\u00f6nderen bir kod oldu\u011funu varsayal\u0131m ve \u00f6yle d\u00fc\u015f\u00fcnelim...\r\n&nbsp;\/\/ \u00e7\u00fcnk\u00fc mevzu logun SMS ile nas\u0131l g\u00f6nderildi\u011fi de\u011fil...\r\n&nbsp;\/\/ ...\r\n&nbsp;\/\/ ...\r\nend;\r\n\r\n{ TLogcu_SQL }\r\n\r\nprocedure TLogcu_SQL.Log(const aLog: String);\r\nbegin\r\n&nbsp;ShowMessage('SQL ile loglama yap\u0131ld\u0131: ' + aLog);\r\n&nbsp;\/\/ Burada SQL veritaban\u0131na LOG atan bir kod oldu\u011funu varsayal\u0131m...\r\n&nbsp;\/\/ ...\r\n&nbsp;\/\/ ...\r\n&nbsp;\/\/ ...\r\nend;\r\n\r\n{ TLogcu_MAIL }\r\n\r\nprocedure TLogcu_MAIL.Log(const aLog: String);\r\nbegin\r\n&nbsp;ShowMessage('Mail ile loglama yap\u0131ld\u0131: ' + aLog);\r\n&nbsp;\/\/ Burada EPOSTA ile LOG g\u00f6nderen bir kod oldu\u011funu varsayal\u0131m...\r\n&nbsp;\/\/ ...\r\n&nbsp;\/\/ ...\r\n&nbsp;\/\/ ...\r\nend;\r\n\r\n{ TLogFabrikasi_SQL }\r\n\r\nfunction TLogFabrikasi_SQL.CreateLogcu: ILogcu;\r\nbegin\r\n&nbsp;\/\/ Factory Method tasar\u0131m deseninin tan\u0131m\u0131na g\u00f6re log tutan bir nesne \u00fcretip d\u0131\u015far\u0131 g\u00f6nderdik...\r\n&nbsp;Result := TLogcu_SQL.Create;\r\nend;\r\n\r\n{ TLogFabrikasi_SMS }\r\n\r\nfunction TLogFabrikasi_SMS.CreateLogcu: ILogcu;\r\nbegin\r\n&nbsp;\/\/ Factory Method tasar\u0131m deseninin tan\u0131m\u0131na g\u00f6re log tutan bir nesne \u00fcretip d\u0131\u015far\u0131 g\u00f6nderdik...\r\n&nbsp;Result := TLogcu_SMS.Create;\r\nend;\r\n\r\n{ TLogFabrikasi_MAIL }\r\n\r\nfunction TLogFabrikasi_MAIL.CreateLogcu: ILogcu;\r\nbegin\r\n&nbsp;\/\/ Factory Method tasar\u0131m deseninin tan\u0131m\u0131na g\u00f6re log tutan bir nesne \u00fcretip d\u0131\u015far\u0131 g\u00f6nderdik...\r\n&nbsp;Result := TLogcu_MAIL.Create;\r\nend;\r\n\r\nend.\r\n<\/code><\/pre>\n<p>Yukar\u0131daki \u00f6rnekte de anla\u015f\u0131ld\u0131\u011f\u0131 \u00fczere bir Factory Method tan\u0131m\u0131n\u0131n nas\u0131l yap\u0131ld\u0131\u011f\u0131na dair doyurucu bir \u00f6rnek g\u00f6rd\u00fc\u011f\u00fcm\u00fcze g\u00f6re art\u0131k bu yap\u0131y\u0131 projelerimizde nas\u0131l kullanaca\u011f\u0131m\u0131za bakmal\u0131y\u0131z. Bunun i\u00e7in bize bir kobay laz\u0131m. Burada Kobay&#8217;dan kas\u0131t, sizin i\u015f nesneleriniz olacak, kapsam\u0131 geni\u015f oldu\u011fundan sadece kobay diye isimlendiriyorum fakat sizin i\u00e7in bu bir ORM nesnesi, bir dataset veya bir form bile olabilir&#8230; Alelade bir kobay nesnesi \u00fcreterek bu mekanizman\u0131n nas\u0131l \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 daha iyi anlayabiliriz.<\/p>\n<p>Ama ondan \u00f6nce, yani daha iyisini \u00f6nermeden \u00f6nce ben de dahil zaman\u0131nda bir\u00e7o\u011fumuzun s\u0131kl\u0131kla d\u00fc\u015ft\u00fc\u011f\u00fc bir yan\u0131lg\u0131ya, k\u00f6t\u00fc bir kodlamaya \u00f6rnek vermek gerekiyor. Bu \u00f6rnek \u00f6nemli, \u00e7\u00fcnk\u00fc konunun k\u0131ymetini artt\u0131r\u0131yor. KirliKobay ad\u0131yla isimlendirdi\u011fim nesneye daha yak\u0131ndan bakal\u0131m;<\/p>\n<pre><code>\r\ninterface\r\n\r\ntype\r\n&nbsp;TKirliKobay = class &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ &nbsp;S\u0131radan bir s\u0131n\u0131f tan\u0131m\u0131\r\n&nbsp; &nbsp;private\r\n&nbsp; &nbsp; &nbsp;Logger: TLogcu_SQL; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ &nbsp;B\u00f6yle bir tip belirtimi sizi bu nesneye (TLogcu_SQL'e) ba\u011f\u0131ml\u0131 yapar. \u0130\u015fte bunu yapmay\u0131n!\r\n&nbsp; &nbsp;public\r\n&nbsp; &nbsp; &nbsp;constructor Create; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ &nbsp;Klasik, herhangi bir nesneyi \u00fcretirken kullland\u0131\u011f\u0131m\u0131z s\u0131radan bir CONSTRUCTOR metodu\r\n&nbsp; &nbsp; &nbsp;destructor Destroy; override; &nbsp; &nbsp; &nbsp;\/\/ &nbsp;Klasik yok edici metodumuz...\r\n&nbsp; &nbsp; &nbsp;procedure Kaydet; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ &nbsp;Loglamay\u0131 tetikleyece\u011fimiz nokta...\r\n&nbsp;end;\r\n\r\nimplementation\r\n\r\nuses\r\n&nbsp;System.SysUtils; &nbsp; \/\/ FreeAndNil\r\n\r\nconstructor TKirliKobay.Create;\r\nbegin\r\n&nbsp;inherited Create; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ &nbsp;\r\n&nbsp; Logger := TLogcu_SQL.Create; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ &nbsp;Do\u011frudan TLoguc_SQL s\u0131n\u0131f\u0131n\u0131 \u00fcrettik ama bu modelde bu asl\u0131nda yanl\u0131\u015f bir davran\u0131\u015f...\r\nend;\r\n\r\ndestructor TKirliKobay.Destroy;\r\nbegin\r\n&nbsp;freeandnil(Logger); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ &nbsp;Do\u011fal olarak, arkam\u0131z\u0131 temizlemek durumunda da kal\u0131yoruz...\r\n&nbsp; inherited Destroy; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ &nbsp;\r\nend;\r\n\r\nprocedure TKirliKobay.Kaydet;\r\nbegin\r\n&nbsp;ShowMessage('TKirliKobay bir \u015feyleri kaydetti');\r\n&nbsp; Logger.Log('Kirli bir loglama yapt\u0131k dolay\u0131s\u0131yla TLogcu_SQL''e art\u0131k mahkumuz');\r\nend;\r\n<\/code><\/pre>\n<p>TKirliKobay nesnesindeki Logger de\u011fi\u015fkenini do\u011frudan TLogcu_SQL nesnesine ba\u011flad\u0131k. \u0130\u015fte problem olan, yanl\u0131\u015f olan nokta asl\u0131nda buras\u0131. \u00c7\u00fcnk\u00fc bu nokta sizin hem kodunuzun esnekli\u011fini bozuyor hem de o nesneye bir ba\u011f\u0131ml\u0131l\u0131k yarat\u0131yor. Halbuki siz istedi\u011finiz log nesnesiyle \u00e7al\u0131\u015fabilmeli bununla birlikte ana kodunuz da bu de\u011fi\u015fiklikten &#8220;hi\u00e7 bir \u015fekilde&#8221; etkilenmemeli&#8230; Yukar\u0131daki KirliKobay nesnesi yine \u00e7al\u0131\u015f\u0131r, yine bir \u015feyleri kaydeder ve SQL&#8217;e loglar atmaya yine devam eder, yani yine i\u015f g\u00f6r\u00fcr ama SQL d\u0131\u015f\u0131nda ba\u015fka bir loglama tekni\u011fi kullanmak isterseniz o zaman sizin ba\u015f\u0131n\u0131z\u0131 a\u011fr\u0131t\u0131r.<\/p>\n<p>E\u011fer daha esnek bir yap\u0131, nesnelerden daha ba\u011f\u0131ms\u0131z bir d\u00fczen kurmak istiyor ve ileriye d\u00f6n\u00fck bir yat\u0131r\u0131m yapmak niyetindeysek bunun do\u011frusu a\u015fa\u011f\u0131daki gibi bir yap\u0131 ile sa\u011flanmal\u0131;<\/p>\n<pre><code>\r\nunit Kobay_Objects_;\r\n\r\ninterface\r\n\r\nuses\r\n&nbsp; &nbsp;Vcl.Dialogs &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ &nbsp;ShowMessage\r\n&nbsp;, FactoryPattern_Objects &nbsp; &nbsp; &nbsp;\/\/ &nbsp;ILogcu, ILogFabrikasi\r\n&nbsp;;\r\n\r\ntype\r\n&nbsp;ELogTipi = (ltSQL, ltSMS, ltMAIL); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ &nbsp;Bu Enumerated Type, bizim bir nesnemizde hangi log ile \u00e7al\u0131\u015faca\u011f\u0131m\u0131z\u0131 se\u00e7memize yard\u0131m edecek, elzem de\u011fil, tamamen bir tercih meselesidir...\r\n&nbsp;TKobay = class &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ &nbsp;Bu bizim kurgusal bir nesnemiz, bunu siz bir TForm, bir TUniConnection gibi bir \u015fey olarak da d\u00fc\u015f\u00fcnebilirsiniz\r\n&nbsp; &nbsp;private\r\n&nbsp; &nbsp; &nbsp;Logger &nbsp; &nbsp; &nbsp; &nbsp;: ILogcu; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ &nbsp;Log tutaca\u011f\u0131m\u0131z nesnenin veri tipinin bir INTERFACE'yi kulland\u0131\u011f\u0131na dikkat edin !!!\r\n&nbsp; &nbsp; &nbsp;LoggerFactory : ILogFabrikasi; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ &nbsp;Log tutma nesnesini \u00fcretece\u011fimiz nesnenin veri tipinin bir INTERFACE'ye i\u015faret etti\u011fine dikkat edin !!!\r\n&nbsp; &nbsp; &nbsp;FLogTipi &nbsp; &nbsp; &nbsp;: ELogTipi;\r\n&nbsp; &nbsp; &nbsp;procedure SetLogTipi(const Value: ELogTipi);\r\n&nbsp; &nbsp;public\r\n&nbsp; &nbsp; &nbsp;constructor Create; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ &nbsp;Klasik, herhangi bir nesneyi \u00fcretirken kullland\u0131\u011f\u0131m\u0131z s\u0131radan bir CONSTRUCTOR metodu\r\n&nbsp; &nbsp; &nbsp;procedure Kaydet; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; \/\/ &nbsp;LOGLAMAYI TET\u0130KLEYECE\u011e\u0130M\u0130Z METOD.\r\n&nbsp; &nbsp; &nbsp;property LogTipi: ELogTipi read FLogTipi write SetLogTipi; &nbsp; &nbsp; &nbsp;\/\/ &nbsp;Logcumuzu bununla belirleyece\u011fiz...\r\n&nbsp;end;\r\n\r\nimplementation\r\n\r\n{ TBirNesne }\r\n\r\nconstructor TKobay.Create; &nbsp; &nbsp; &nbsp; \/\/ Kurgusal nesnemizi \u00fcretece\u011fimiz CONSTRUCTOR metod.\r\nbegin\r\n&nbsp;inherited Create; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ Kurgusal nesnemizi \u00fcretiyoruz.\r\n&nbsp;LogTipi := ltSQL; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;\/\/ Bir ba\u015flang\u0131\u00e7 de\u011feri olarak SQL ile loglama yapaca\u011f\u0131m\u0131z\u0131 belirtmi\u015f olduk.\r\nend;\r\n\r\nprocedure TKobay.SetLogTipi(const Value: ELogTipi);\r\nbegin\r\n&nbsp; FLogTipi := Value;\r\n\r\n&nbsp;\/\/ Bu noktada biz yine soyut bir arabirim vas\u0131tas\u0131yla Logcu \u00fcreten bir fabrikadan faydalanmak istedi\u011fimizi belirtiyoruz\r\n&nbsp; \/\/ Se\u00e7ti\u011fimiz tipe g\u00f6re fabrika arabirimimiz bize bir LOG FABR\u0130KASI \u00fcretiyor\r\n&nbsp; case &nbsp;Value &nbsp; of\r\n&nbsp; &nbsp;&nbsp; &nbsp; &nbsp;ltSMS : LoggerFactory := TLogFabrikasi_SMS.Create;\r\n&nbsp; &nbsp;&nbsp; &nbsp; &nbsp;ltSQL : LoggerFactory := TLogFabrikasi_SQL.Create;\r\n&nbsp; &nbsp;&nbsp; &nbsp; &nbsp;ltMAIL: LoggerFactory := TLogFabrikasi_MAIL.Create;\r\n&nbsp; end;\r\n\r\n&nbsp;\/\/ Bu noktada hangi fabrikay\u0131 kulland\u0131\u011f\u0131m\u0131z\u0131n art\u0131k bizim i\u00e7in bir anlam\u0131 yok, \u00e7\u00fcnk\u00fc hangi fabrika olursa olsun, biz bize bir log tutan nesne gelece\u011fini art\u0131k biliyoruz.\r\n&nbsp;Logger := LoggerFactory.CreateLogcu; \/\/ Yukar\u0131daki tercihimiz ne olursa olsun art\u0131k, fabrikam\u0131z bize bir LOGCU nesnesi \u00fcretiyor\r\nend;\r\n\r\nprocedure TKobay.Kaydet;\r\nbegin\r\n&nbsp;\/\/ Bu metod, bizim kobay nesnemizin bir\u015feyleri kaydetti\u011fi nokta.\r\n&nbsp;\/\/ Temsili olarak verinin bir yerlere kaydedildi\u011fini varsayal\u0131m...\r\n&nbsp;ShowMessage('Veri Kaydedildi');\r\n\r\n&nbsp;\/\/ Buras\u0131 ise LOG tuttu\u011fumuz nokta, \u015fimdi size bir soru LOGGER hangi nesneyi kullan\u0131yor? LOGGER'in tipi ne sizce?\r\n&nbsp; Logger.Log('TBirNesne.Kaydet'); &nbsp; \/\/ Logger'in tipinin ne oldu\u011funun art\u0131k bu noktadan sonra bir \u00f6nemi yok \u00e7\u00fcnk\u00fc siz bunu zaten yukar\u0131da belirttiniz, sizin i\u00e7in art\u0131k bu noktadan sonra log d\u00fczg\u00fcn tutulmu\u015f mu tutulmam\u0131\u015f m\u0131 ona bakman\u0131z gerekir...\r\nend;\r\n\r\nend.\r\n<\/code><\/pre>\n<p>Kobay\u0131m\u0131z\u0131 da tan\u0131mlad\u0131\u011f\u0131m\u0131za g\u00f6re art\u0131k projemizde bunu nas\u0131l kullanabilirve test edebiliriz basit bir \u00f6rnekle g\u00f6relim;<\/p>\n<pre><code>\r\nunit Ana_;\r\n\r\ninterface\r\n\r\nuses\r\n&nbsp;Kobay_Objects_, \/\/ TKobay &nbsp;( BU ARADA LOGCU VE LOGFABRIKASI ile ilgili herhangi bir uniti \u00e7a\u011f\u0131rmad\u0131k dikkat ettiyseniz... )\r\n\r\n&nbsp;Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;\r\n\r\ntype\r\n&nbsp;TAna = class(TForm)\r\n&nbsp; &nbsp;BT_Save: TButton;\r\n&nbsp; &nbsp;procedure FormCreate(Sender: TObject);\r\n&nbsp; &nbsp;procedure FormDestroy(Sender: TObject);\r\n&nbsp; &nbsp;procedure BT_SaveClick(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; &nbsp;NesneninTeki: TKobay;\r\n&nbsp;end;\r\n\r\nvar\r\n&nbsp;Ana: TAna;\r\n\r\nimplementation\r\n\r\n{$R *.dfm}\r\n\r\nprocedure TAna.FormCreate(Sender: TObject);\r\nbegin\r\n&nbsp;\/\/ Formumuzun OnCreate olay\u0131na kobay nesnemizi \u00fcreten bir kod ekliyoruz\r\n&nbsp;NesneninTeki := TKobay.Create;\r\nend;\r\n\r\nprocedure TAna.FormDestroy(Sender: TObject);\r\nbegin\r\n&nbsp;\/\/ Formumuz yok edilmeden hemen \u00f6nce kobay nesnemizi yok ediyoruz...\r\n&nbsp;FreeAndNil(NesneninTeki);\r\nend;\r\n\r\nprocedure TAna.BT_SaveClick(Sender: TObject);\r\nbegin\r\n&nbsp;\/\/ &nbsp;SAVE adl\u0131 butona bast\u0131\u011f\u0131m\u0131zda kobay nesnenin loglama tipini her seferinde de\u011fi\u015ftiren bir yap\u0131 kurduk\r\n&nbsp;\/\/ &nbsp;Bu sadece yap\u0131n\u0131n dinamikli\u011fini sergilemek amac\u0131yla b\u00f6yle yap\u0131ld\u0131, butona her bast\u0131\u011f\u0131n\u0131zda loglama metodu de\u011fi\u015fecek...\r\n&nbsp;case NesneninTeki.LogTipi of\r\n&nbsp; &nbsp; &nbsp; ltSMS : NesneninTeki.LogTipi := ltSQL;\r\n&nbsp; &nbsp; &nbsp; ltSQL : NesneninTeki.LogTipi := ltMAIL;\r\n&nbsp; &nbsp; &nbsp; ltMAIL: NesneninTeki.LogTipi := ltSMS;\r\n&nbsp;end;\r\n\r\n&nbsp;\/\/ kobay nesnemiz bir \u015feyleri kaydedip hemen kendi i\u00e7inde bir de log tutuyor fakat bu i\u015fler arka tarafta yap\u0131lm\u0131\u015f oluyor...\r\n&nbsp; NesneninTeki.Kaydet;\r\nend;\r\n\r\nend.\r\n<\/code><\/pre>\n<p>G\u00f6rd\u00fc\u011f\u00fcn\u00fcz gibi ba\u015flarda \u00e7ok karma\u015f\u0131km\u0131\u015f gibi gelse de asl\u0131nda gayet basit ve gayette temiz bir yap\u0131. Projenizdeki kodu y\u00f6netebilmenize ve onu daha esnek hale getirebilmenize \u00e7ok fayda sa\u011fl\u0131yor. \u0130\u015fin ba\u015f\u0131nda belki biraz yorulabilirsiniz ama terledi\u011finize de\u011fecektir&#8230;<\/p>\n<p>Bu arada fark ettiniz mi bilmiyorum ama kobay nesnemiz haricinde hi\u00e7 bir yerde free ve destroy gibi dispose edici, yokedici metodlar\u0131 \u00e7a\u011f\u0131rmad\u0131k. Sizce bir yerlerde memory leak olu\u015fmu\u015f mudur? ( Bunu bir ev \u00f6devi olarak kabul edin ve sebeplerini birazc\u0131k ara\u015ft\u0131r\u0131n, interface&#8217;ler alt\u0131nda yatan harika bir mekanizman\u0131n oldu\u011funu fark edeceksiniz \ud83d\ude42 )<\/p>\n<p>Umar\u0131m faydal\u0131 olmu\u015ftur, ba\u015fka bir yaz\u0131da g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Tamam\u0131n\u0131 elden ge\u00e7irmektense sadece tek bir parametreyi de\u011fi\u015ftirerek projenizin mevcut davran\u0131\u015f\u0131n\u0131 yeniden d\u00fczenlemek veya ek davran\u0131\u015flar geli\u015ftirmek istedi\u011finiz zamanlar oldu mu? &#8220;Biz zaten b\u00f6yle \u015feyler yapabiliyoruz&#8221; dedi\u011finizi duyar gibiyim&#8230; Kaz\u0131n aya\u011f\u0131 ger\u00e7ekten de \u00f6yle mi acaba? Bu konuda birileri kafa yormu\u015f&#8230;<\/p>\n","protected":false},"author":1,"featured_media":267,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[4,37,36],"class_list":["post-172","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-delphi","tag-factory-method","tag-tasarim-desenleri"],"_links":{"self":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/172","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=172"}],"version-history":[{"count":1,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/172\/revisions"}],"predecessor-version":[{"id":179,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/172\/revisions\/179"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/media\/267"}],"wp:attachment":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=172"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}