{"id":186,"date":"2019-09-30T22:33:21","date_gmt":"2019-09-30T19:33:21","guid":{"rendered":"http:\/\/www.potansif.com\/?p=186"},"modified":"2019-10-01T16:20:15","modified_gmt":"2019-10-01T13:20:15","slug":"tasarim-desenleri-observer-design-pattern","status":"publish","type":"post","link":"http:\/\/www.potansif.com\/?p=186","title":{"rendered":"Tasar\u0131m Desenleri : Observer Design Pattern"},"content":{"rendered":"<p>Bu sefer ad\u0131n\u0131 \u00e7ok duydu\u011fumuz, bir \u00e7ok yerde kar\u015f\u0131la\u015fabildi\u011fimiz, ger\u00e7ek hayattaki i\u015fleyi\u015fe \u00e7ok benzeyen bir tasar\u0131m desenini tan\u0131tmaya \u00e7al\u0131\u015faca\u011f\u0131m: Observer Design Pattern.<!--more--><\/p>\n<p>Observer&#8217;\u0131n, kelime anlam\u0131 &#8220;G\u00f6zlemci&#8221; demektir. Observer Tasar\u0131m Deseni, &#8220;\u00f6zne&#8221; konumundaki bir nesnenin kendisine ba\u011f\u0131ml\u0131 olan di\u011fer nesnelere kendisinde ger\u00e7ekle\u015fen bir ko\u015ful, olay veya durum de\u011fi\u015fikli\u011fini otomatik olarak bildirmesini, bu sayede de onlar\u0131n kendilerini g\u00fcncellenmesini tetikleyen bir yap\u0131y\u0131 tarif eder. Bu yap\u0131da ba\u011f\u0131ml\u0131l\u0131klar\u0131n listesini tutan ve de\u011fi\u015fiklikleri takip eden &#8220;\u00f6zne&#8221; konumunda bir ana nesne ve bu nesneye bildirim ba\u011flam\u0131nda ba\u011f\u0131ml\u0131 olan &#8220;G\u00f6zlemci&#8221; konumundaki birden \u00e7ok alt nesne yer al\u0131r. Alt nesnelerin veya abonelerin ortak bir ata nesneden t\u00fcretilmi\u015f olmas\u0131 tercih edilir. Ortak bir atadan t\u00fcretilmeseler bile kendi yap\u0131lar\u0131nda bir &#8220;Update&#8221; metodunu bar\u0131nd\u0131rmalar\u0131 gerekmektedir&#8230; \u00d6z\u00fcnde bu tasar\u0131m deseni, &#8220;\u00d6zne&#8221; ile &#8220;G\u00f6zlemciler&#8221; aras\u0131ndaki etkile\u015fimin nas\u0131l y\u00f6netilece\u011fini yani bire \u00e7ok olay i\u015flemeyi nas\u0131l ger\u00e7ekle\u015ftirebilece\u011fimizi tarif etmektedir.<\/p>\n<p>Yukar\u0131daki paragraftan bu desenin \u00e7ok basit bir yap\u0131s\u0131 oldu\u011fu izlenimine kap\u0131labilirsiniz. Endi\u015felenmeyin hakl\u0131s\u0131n\u0131z, asl\u0131nda bu kadar basit. Fakat tasar\u0131m desenini daha iyi anlamak i\u00e7in bu desenin \u00e7al\u0131\u015fma bi\u00e7imini bir hikaye \u00fczerinden de anlatmay\u0131 deneyebiliriz&#8230;<\/p>\n<p>Diyelim ki siz bir bankac\u0131s\u0131n\u0131z ve m\u00fc\u015fterilerinize yat\u0131r\u0131m dan\u0131\u015fmanl\u0131\u011f\u0131 yap\u0131yorsunuz. 3 tane m\u00fc\u015fteriniz var, bu m\u00fc\u015fteriler Dolar \u00fczerinden al-sat i\u015flemleri yap\u0131yor fakat bu konuda sizden dan\u0131\u015fmanl\u0131k hizmeti al\u0131yor&#8230; Siz dolar piyasas\u0131n\u0131 takip ederken dolar d\u00fc\u015fmeden \u00f6nce m\u00fc\u015fterilerinize &#8220;sat&#8221;, y\u00fckselmeden \u00f6nce &#8220;al&#8221; \u00f6nerisinde bulunuyorsunuz. \u0130\u015fte Observer tasar\u0131m deseni de asl\u0131nda bu etkile\u015fimin nas\u0131l y\u00f6netilece\u011fini tarif ediyor. bu senaryoya g\u00f6re siz &#8220;\u00d6zne&#8221; (subject), m\u00fc\u015fterileriniz &#8220;G\u00f6zlemci&#8221; (observer), sizin &#8220;al&#8221; veya &#8220;sat&#8221; talimatlar\u0131n\u0131z &#8220;Bildirim&#8221; (Notification, NotifyObservers), m\u00fc\u015fterilerinizin &#8220;alma&#8221; veya &#8220;satma&#8221; eylemi &#8220;G\u00fcncelleme&#8221; (update) anlam\u0131na geliyor. Burada birisinin size m\u00fc\u015fteri olmas\u0131 durumu &#8220;aboneli\u011fi ba\u015flat\u0131yor&#8221; (RegisterObserver), m\u00fc\u015fteriniz ile sizden aran\u0131zdaki i\u015f ili\u015fkisinin sona ermesi ise &#8220;aboneli\u011fi bitiriyor&#8221; (UnRegisterObserver). Son olarak portf\u00f6y\u00fcn\u00fcz ise &#8220;M\u00fc\u015fteri Listeniz&#8221; (yani ObserverCollection) anlam\u0131na geliyor&#8230;<\/p>\n<p>Bunu bir de a\u015fa\u011f\u0131daki gibi bir UML diyagram\u0131nda g\u00f6sterelim.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-624\" src=\"http:\/\/rubicube.com.tr\/wp-content\/uploads\/2018\/10\/Observer.png\" alt=\"\" width=\"800\" height=\"331\"><\/p>\n<p>Yukar\u0131daki senaryoyu ve UML diyagram\u0131n\u0131 bir Pascal kodu ile \u00f6rneklendirmeye \u00e7al\u0131\u015fay\u0131m;<\/p>\n<pre><code>\r\nunit Observer_Objects_;\r\n \r\ninterface\r\n \r\nuses\r\n   Vcl.Dialogs                         \/\/  ShowMessage\r\n , System.Generics.Collections         \/\/  TList, <del>TObjectList<\/del>\r\n ;\r\n \r\n {\r\n Tasar\u0131m deseninde \u00f6nerilen kal\u0131ptan uzakla\u015fmamak ad\u0131na nesne ve de\u011fi\u015fken isimlerini UML diyagram\u0131ndaki isimlerle benze\u015ftirdim.\r\n Bu sayede UML diyagram\u0131nda g\u00f6sterilen nesnelerin Delphi kodunda nereye denk geldi\u011fini daha kolay anlam\u0131\u015f olaca\u011f\u0131z. Fakat siz bu\r\n isimlendirmeye uymak durumunda de\u011filsiniz. Bu tasar\u0131m deseninde \u00f6nemli olan, bu t\u00fcr bir mekanizmay\u0131 hayata ge\u00e7irebilmeniz...\r\n }\r\n \r\ntype\r\n \/\/ G\u00f6zlemcilerimiz i\u00e7in ortak bir arabirim tan\u0131ml\u0131yoruz. Di\u011fer g\u00f6zlemci s\u0131n\u0131flar\u0131n\u0131 bu arabirimden t\u00fcretece\u011fiz\r\n \/\/ veya bu arabirimi kullanarak ilgili s\u0131n\u0131flara adapt\u00f6r yazabilece\u011fiz... Bu sayede abonelerin yok edilmesi s\u0131ras\u0131nda\r\n \/\/ Bellek y\u00f6netimini en az eforla sa\u011flam\u0131\u015f olaca\u011f\u0131z.\r\n IObserver = interface\r\n     procedure Update(aTalimat: String); \/\/ Bu metod arac\u0131l\u0131\u011f\u0131yla abonelerin kendierini g\u00fcncellemesini tetikleyebilece\u011fiz.\r\n end;\r\n \r\n \/\/ IObserver s\u0131n\u0131f\u0131ndan t\u00fcretilen a\u015fa\u011f\u0131daki iki s\u0131n\u0131f ise birbirinden farkl\u0131 nesnelere dikkatinizi \u00e7ekmek amac\u0131yla tan\u0131mland\u0131.\r\n \/\/ UML Grafi\u011finde bu durumu sar\u0131 renklerde vurgulanm\u0131\u015f bir \u015fekilde g\u00f6rmektesiniz.\r\n TConcreateObserver_A = class(TInterfacedObject, IObserver) \/\/ bu s\u0131n\u0131f\u0131 bir bakkal veya bir market gibi d\u00fc\u015f\u00fcn\u00fcn\r\n   public\r\n     procedure Update(aTalimat: String);  \/\/ Bu, \"A\" s\u0131n\u0131f\u0131na \u00f6zg\u00fc fiili bir g\u00fcncelleme yapacak..\r\n end;\r\n TConcreateObserver_B = class(TInterfacedObject, IObserver) \/\/ bu s\u0131n\u0131f\u0131 da bir f\u0131r\u0131nc\u0131 veya pastane gibi d\u00fc\u015f\u00fcn\u00fcn\r\n   public\r\n     procedure Update(aTalimat: String);  \/\/ Bu ise \"B\" s\u0131n\u0131f\u0131na \u00f6zg\u00fc fiili bir g\u00fcncelleme yap\u0131lacak...\r\n end;\r\n \r\n \/\/ \u00d6zne tan\u0131m\u0131m\u0131z\u0131 bir Interface olarak yap\u0131yoruz.\r\n ISubject = interface\r\n   function  GetObserverCollection: TList;\r\n   procedure SetObserverCollection(aObserverCollection: TList);\r\n \r\n   property  ObserverCollection: TList        \/\/ Bu bizim abone listemiz, S\u0131n\u0131f\u0131 bir Interface de\u011fil de bir Abstract\r\n        read GetObserverCollection                       \/\/ s\u0131n\u0131f olarak san\u0131mlasayd\u0131k bunu bir property\r\n       write SetObserverCollection;                      \/\/ yerine do\u011frudan bir de\u011fi\u015fken olarak da kullanabilirdik.\r\n \r\n   procedure NotifyObservers(aTalimat: string);          \/\/ Bu t\u00fcm g\u00f6zlemcilerimize durum de\u011fi\u015fikli\u011fini toplu olarak bildirir\r\n   procedure RegisterObserver(aObserver: IObserver);     \/\/ Bu bizim yeni aboneyi listeye ekledi\u011fimiz metod\r\n   procedure UnRegisterObserver(aObserver: IObserver);   \/\/ Bu bizim mevcut abonemizi listeden \u00e7\u0131karacak olan metodumuz\r\n   procedure TEST(aTalimat: String);                     \/\/ Durum de\u011fi\u015fikli\u011finin ger\u00e7ekle\u015fece\u011fi temsili bir metoddur.\r\n end;\r\n \r\n TSubject = class(TInterfacedObject, ISubject)\r\n   private\r\n \r\n     FObserverCollection: TList;              \/\/ Bu de\u011fi\u015fken asl\u0131nda bizim abonelerimizin listesini tutacak\r\n     function GetObserverCollection: TList;\r\n     procedure SetObserverCollection(aObserverCollection: TList);\r\n     procedure NotifyObservers(aTalimat: string);\r\n   protected\r\n   public\r\n     constructor Create;\r\n     destructor Destroy; override;\r\n \r\n     \/\/ Bu bizin s\u00fcreci tetikledi\u011fimiz metod. Bu herhangi ba\u015fka bir metod da olabilir. UML \u00e7iziminde bunu g\u00f6rmezsiniz\r\n     \/\/ \u00e7\u00fcnk\u00fc bu k\u0131s\u0131mm her t\u00fcrl\u00fc tetiklemeyi temsil ediyor.\r\n     procedure TEST(aTalimat: String);\r\n     procedure RegisterObserver(aObserver: IObserver);\r\n     procedure UnRegisterObserver(aObserver: IObserver);\r\n     property  ObserverCollection: TList\r\n         read  GetObserverCollection\r\n         write SetObserverCollection;\r\n end;\r\n \r\nimplementation\r\n \r\n{ TSubject }\r\n \r\nconstructor TSubject.Create;\r\nbegin\r\n inherited Create;\r\n FObserverCollection := TList.Create;\r\nend;\r\n \r\ndestructor TSubject.Destroy;\r\nbegin\r\n FObserverCollection.Destroy; \/\/ FreeAndNil ( FObserverCollection ); de kullan\u0131labilir.\r\n inherited Destroy;\r\nend;\r\n \r\nprocedure TSubject.RegisterObserver(aObserver: IObserver);\r\nbegin\r\n GetObserverCollection.Add(aObserver)\r\nend;\r\n \r\nprocedure TSubject.UnRegisterObserver(aObserver: IObserver);\r\nbegin\r\n GetObserverCollection.Remove(aObserver);\r\nend;\r\n \r\nprocedure TSubject.NotifyObservers(aTalimat: string);\r\nvar\r\n aObserver: IObserver;\r\nbegin\r\n for aObserver in GetObserverCollection    \/\/ G\u00f6zlemci listemizdeki her bir g\u00f6zlemciyi tek tek ziyaret edip\r\n  do aObserver.Update(aTalimat);           \/\/ kendisini g\u00fcncellemesini sa\u011fl\u0131yoruz.\r\nend;\r\n \r\nfunction TSubject.GetObserverCollection: TList;\r\nbegin\r\n Result := FObserverCollection;\r\nend;\r\n \r\nprocedure TSubject.SetObserverCollection(aObserverCollection: TList);\r\nbegin\r\n FObserverCollection := aObserverCollection;\r\nend;\r\n \r\nprocedure TSubject.TEST(aTalimat: String);\r\nbegin\r\n \/\/ Buras\u0131 ise fiilen durumun de\u011fi\u015fti\u011fi k\u00f6k noktam\u0131z.\r\n ShowMessage('G\u00f6zlemci Listesindeki her bir g\u00f6zlemciye \u015fu talimat\u0131 verdim = ' + aTalimat);\r\n \r\n \/\/ Durum de\u011fi\u015fikli\u011fi ger\u00e7ekle\u015ftikten sonra olu\u015fan yeni konjonkt\u00fcr\u00fc g\u00f6zlemcilerimize bildiriyoruz.\r\n NotifyObservers(aTalimat);\r\nend;\r\n \r\n{ TConcreateObserver_A }\r\n \r\nprocedure TConcreateObserver_A.Update(aTalimat: String);\r\nbegin\r\n \/\/ A tipindeki bu g\u00f6zlemciyi mesela bir bakkal olarak d\u00fc\u015f\u00fcnebilirsiniz\r\n ShowMessage('A S\u0131n\u0131f\u0131na g\u00f6re de\u011fi\u015fik bir g\u00fcncelleme i\u015flemi yapt\u0131k = ' + aTalimat);\r\nend;\r\n \r\n{ TConcreateObserver_B }\r\n \r\nprocedure TConcreateObserver_B.Update(aTalimat: String);\r\nbegin\r\n \/\/ B tipindeki bu g\u00f6zlemcisi ise misalen bir f\u0131r\u0131nc\u0131 olarak d\u00fc\u015f\u00fcnebilirisinis.\r\n ShowMessage('B S\u0131n\u0131f\u0131na g\u00f6re \u00e7ok farkl\u0131, emsalsiz bir ba\u015fka g\u00fcncelleme i\u015flemi daha yapt\u0131k = ' + aTalimat);\r\nend;\r\n \r\nend.\r\n<\/code><\/pre>\n<p>Gelelim, \u015fimdi bu yap\u0131n\u0131n nas\u0131l kullan\u0131ld\u0131\u011f\u0131na.<\/p>\n<pre><code>\r\nimplementation\r\n \r\nuses\r\n   Observer_Objects_                                             \/\/ S\u0131n\u0131f\u0131n tan\u0131ml\u0131 oldu\u011fu Uniti kullanaca\u011f\u0131z.\r\n ;\r\n \r\n{$R *.dfm}\r\n \r\nprocedure TAna.Button1Click(Sender: TObject);                     \/\/ Bir butonun OnClick olay\u0131na\r\nvar\r\n KurTakipcisi: TSubject;                                         \/\/ \u00f6zne konumundaki bir nesneyi de\u011fi\u015fken olarak tan\u0131mlad\u0131k\r\nbegin\r\n KurTakipcisi := TSubject.Create;                                \/\/ \u00d6zneyi olu\u015fturduk\r\n KurTakipcisi.RegisterObserver(TConcreateObserver_A.Create);     \/\/ A t\u00fcr\u00fcnden bir g\u00f6zlemci \/ abone \/ alt nesne olu\u015fturduk\r\n KurTakipcisi.RegisterObserver(TConcreateObserver_B.Create);     \/\/ B t\u00fcr\u00fcnden ba\u015fka bir g\u00f6zlemci \/ abone \/ alt nesne olu\u015fturduk\r\n KurTakipcisi.RegisterObserver(TConcreateObserver_A.Create);     \/\/ A t\u00fcr\u00fcnden ba\u015fka bir g\u00f6zlemci \/ abone \/ alt nesne olu\u015fturduk\r\n KurTakipcisi.RegisterObserver(TConcreateObserver_B.Create);     \/\/ B t\u00fcr\u00fcnden ba\u015fka bir g\u00f6zlemci \/ abone \/ alt nesne olu\u015fturduk\r\n \r\n KurTakipcisi.TEST('Al');                                        \/\/ durum de\u011fi\u015fikli\u011fini tetiklemek i\u00e7in \"AL\" emri verdik\r\n \r\n FreeAndNil(KurTakipcisi);                                       \/\/ \u00d6znemizi ve ona ba\u011fl\u0131 olan t\u00fcm aboneleri bellekten temizledik.\r\nend;\r\n \r\n\/\/ VEYA BA\u015eKA B\u0130R KULLANIM \u015eEKL\u0130 (ASLINDA AYNI. SADECE ABONELER\u0130N K\u0130M OLDU\u011eUNU DAHA NET B\u0130L\u0130YORUZ )\r\n \r\nprocedure TAna.Button2Click(Sender: TObject);                     \/\/ BA\u015eKA bir butonun OnClick olay\u0131na\r\nvar\r\n KurTakipcisi : TSubject;                                        \/\/ \u00d6zne konumunda olan bir BANKACIYI de\u011fi\u015fken olarak tan\u0131mlad\u0131k\r\n Firinci      : TConcreateObserver_A;                            \/\/ A tipli\r\n Bakkal       : TConcreateObserver_B;                            \/\/ B tipli\r\nbegin\r\n Firinci      := TConcreateObserver_A.Create;                    \/\/ Bir f\u0131r\u0131nc\u0131 olu\u015fturduk.\r\n \r\n KurTakipcisi := TSubject.Create;                                \/\/ Bankac\u0131m\u0131z\u0131 olu\u015fturduk.\r\n KurTakipcisi.RegisterObserver( Firinci );                       \/\/ F\u0131r\u0131nc\u0131m\u0131z\u0131 abone listesine ald\u0131k\r\n KurTakipcisi.RegisterObserver( TConcreateObserver_B.Create );   \/\/ B tipinde ba\u015fka birisi bize abone oldu\r\n \r\n Bakkal       := TConcreateObserver_B.Create;                    \/\/ Bir bakkal olu\u015fturduk\r\n KurTakipcisi.RegisterObserver( Bakkal );                        \/\/ Bakkal\u0131m\u0131z\u0131 abone listesine ald\u0131k\r\n \r\n KurTakipcisi.TEST('Sat');                                       \/\/ t\u00fcm abonelere Satma y\u00f6n\u00fcnde talimat verdik\r\n \r\n KurTakipcisi.UnRegisterObserver( Firinci );                     \/\/ F\u0131r\u0131nc\u0131 bizim hizmetten memnun kalmad\u0131\u011f\u0131 i\u00e7in listemizden \u00e7\u0131kard\u0131k...\r\n \r\n KurTakipcisi.TEST('Al');                                        \/\/ geri kalan t\u00fcm abonelere Alma y\u00f6n\u00fcnde talimat verdik...\r\n \r\n FreeAndNil(KurTakipcisi);\r\nend;<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Bu sefer ad\u0131n\u0131 \u00e7ok duydu\u011fumuz, bir \u00e7ok yerde kar\u015f\u0131la\u015fabildi\u011fimiz, ger\u00e7ek hayattaki i\u015fleyi\u015fe \u00e7ok benzeyen bir tasar\u0131m desenini tan\u0131tmaya \u00e7al\u0131\u015faca\u011f\u0131m: Observer Design Pattern.<\/p>\n","protected":false},"author":1,"featured_media":261,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[4,62,36],"class_list":["post-186","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-delphi","tag-observer","tag-tasarim-desenleri"],"_links":{"self":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/186","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=186"}],"version-history":[{"count":1,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/186\/revisions"}],"predecessor-version":[{"id":187,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/posts\/186\/revisions\/187"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=\/wp\/v2\/media\/261"}],"wp:attachment":[{"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=186"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=186"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.potansif.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=186"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}