Desing Pattern notlarım

 Selamlar, buraya ara ara izleyip notlar aldığım desing pattern ile ilgili yazıları mı koyacağım, aslında aktif not alırken not alma yeteneğimin gelişmemiş olduğun fark etsem de zamanla daha iyiye gideceğini umut ediyorum. Buradakiler oturup not alıp buraya aktardıklarım şeklinde olduğu için formatları - dili gerçekten karışık olacaktır, iteratif şekilde baktıkça daha iyiye gideceğini düşünüyorum:

Başlamadan başlıca kullandığım kaynaklar:

Design Patterns in the Real World, an Analysis-Based Approach queue By Allen Holub, O'relly videoları

refactoring guru sitesi

Son güncellenme: 19.03.2022

* => o methodun yapılıs sekli

! => genel uyarı yada genel bilgiler


=== TEMPLATE METHOD ===

! object ask for help not for information


-------

shape

-------

color, graphics

----------------

draw(graphics) --> bu method draw {

|       preareGraphıcs(g); doDrawing(g); }

|

|

|

  --------------------------------

| |

circle line

..kendine ait elemanlar

doDragwing(graphics g)



* draw ile adımları belirliyor prepare graphics aslında base clasta implement edilebilen ortak bir yapı iken doDraw shapelere özgü bir method

* onları alt sınıflara indirip her birinin sadece kendi işini yapmasını söylüyoruz (ask for help not for information!!)

* boylelikle superclass kendine ait infoyu dısarı cıkarmaz

* ama alt classlarda kendine ait olan sekilde islemlerine devam eder


! koda bakıp bu ne patterni olur değil, soruna bakıp temel prensiplere yönelik bu sorunu çözdüğünde desing patternları uygularsın


UYGULANABİLİRLİK

 subclasların yada eklenebilecek yeni classların bazı adımları override edebileceği(kendine uygun sekilde gerçeklemek istediği) durumlarda yapılabilir

 tek büyük bir algoritmayi adımlara bölüp devam ediliyor

 birden fazla class benzer algoritmaları küçük farklılıklarla aynı şekilde impl ettiyse aslında adımlara bölüp ortak kısımları yukarı taşımayı görebilirsin

 


HOW TO IMPLEMENT

 hedeflenen algoritmayı adımlara bolup hangi adımların ortak hangilerinin sublcasslarda uniq olarak cozuldugunu bul

 abstract base class icerisinde (final olabilir) adımları içeren bir method olustur (örn: templateMethod() { step1(); step2(); step3(); }; )

 bazı adımları base classta implement edebilirsin yada hepsi abstract olabilir, ortak kullanıma gore imp edilebilir

 

REAL WORLD EXAMPLE

rapor alacaksın, bu birden fazla adımda oluşuyor 

 Hesapla

 Çıktıyı üret

 Kaydet 

 Notification oluştur

gibi adımlardan olusabilir,

farklı tipte rapolar var ve bazılarında notification ve hepsinde raporu üretme adımları farklı sekilde implement edilmeli

Bazıları raporu fakkrli şekilde kaydedecekleri veya uretecekleri için onlar kendi methodlarini implement edebilir


Abstract ReportTemplate

Public final doReport() {

 GenereteReport()

 SaveReport()

 Notify()

}

.... Alt adimlar

Burada notfy ve save implement edilir alt sınıflar isterler ise imp ederler, generateReport ise abstract olarak bırakılabilir 


//concarate bir sınıf

pubclic class FinanceReport extends ReportTemplate

Generate() {...} //implement edilir sadece 


//böylelikle bir sınıf olsutruduğumuzda

financeReport.doReport();

// diyerek kullanabiliriz


====BUILDER ======= 


! open/close sistemler gelisime acık ama degişime kapalı olmalı

bunu tabikide subclass ekleyerek yapabilirsin ama bu base classı kırılgan yapar, herhangi bir zorunlu degisiklik imkansız olur

* parenti degistirince builderlarda bundan etkileniyor bu durumdan bu pattern bizi kurtarmasada ne kadar yeri değiştireceğimizi biliyoruz

yani bu sorunu çözmesede değişiklik yapılan hedefi belirli oluyor


<<interface>>

Builder <------------- Director, makeBuildConcatetype1(); makeBuildConcareteType2();

---------- bu arkas builderları alıp adımaları spesifik sıra ile çağırıyor 

methodlar.... yani buna new Director(jsonExporter); director.exportJson() olarak cağırabilyiorsun farklı versiyonları yapar 

| zorunlu değil yapım sırasını yöneten sınıf görevindedir

|

--------------------------------------

builderConcarate1 builderConcarate2


* örneğin exporter yapacağız, exporter isimli bir interface olustup

* jsonExporter ve XmlExporter claslarını yapabiliriz, bunlar interfacedeki (exporName methodu olsun diyelim) exportName(name) { convertJson( getName()) } gibi sekilde methodları var

* dediğimiz gibi bir sey değistiğinde bu interfacei implement eden methodları değiştirerek aslında değişim scopunu biliyor oluyor


UYGULANABİLİRLİK

 teleskopik constructor yapısı oldugu zaman, a degiskeni ile bu sunıfı olustur, a ve b ile olustur a,b,c ile olustur..., builder adım adım bunları olusturmaya yarar

 bir sınıfın bir den fazla "represantation" u olusturman gerektiğinde, xml json gibi aslında "data layer" ile "ui layer" i ayırıyorsun

 adım adım olusturulması gereken karmasık bir obje varsa da kullanılabilir


HOW TO İMPLEMENT

 make sure steps of constructions for building all availible product representation

 adımları interfacede tanımla

 her bir concarete sınıfı yarat 

 director class olıısturabilirsin, bu olıusturma sırasını ve asamasını encapsule etmene yardımcı olur

 client class directore builder gecirir, director bu builder ile productı olusturur


REAL-WORLD EXAMPLE

 SqlQuery builder, jsonBuilder sınıfları, 

 örneğin export alacak bir yapı, json ve xml tipinde builder oluşturup, director sınıfına bu bilderi geçirerek kullanabilirsin (bir clasın birden farklı şekilde represantation'u olmuş oluyor burada aslında)


===SINGLETON===

* temel olarak bir objeden sadece bir tane olusacağına garanti veren bir objedir.

* amaç aslında bir tane obje olusturarak örneğin database connection gibi bir şeyi oluşturan tek bir obje olması, burada tek bir yerden yaratılıp kullanılması gereken resource'lar olduğu gibi oluşturulması maliyetli bir objeninde sadece bir kez oluşturulup kaynakları verimli kullanmamıza da imkan vermesinden dolayı kullanılanılır

* global olarak erişilebilen bir objedir

* spring gibi freamworklerde stateless servisler de singletion olarak oluşturulup kullanılır, buradaki fark bu objeyi fremwork oluşturduğu için singletion olarak yaratır, obje singletion mantığını kendi iç yapısında tutmaz (aslında yapısal olarak singletion değildir birden fazla instance olusutulabbilir)

* birden fazla şekilde implement edebilirsin

* static initiliaziton yöntemleri, kötü tarafı program başlarken ihtiyaç duyulmasına bakılmaksızın oluşturulacaktır

* layzy init yaklaşımı ile program ihtiyaç duyguğunda oluşturulmalı, constructer'i  private yapıp, getInstance() methodunun arkasına (thread safe olacak şekilde) eğer bir instance yok ise oluştur var ise olanı döndür olarak bir logic ile objeyi oluşturabilirsin

* thread safe kısmına dikkat edilmeli

* java da 

if null == instance //burada her instance isteiğimizde yaratılmıs bir nesnede synronized olmadan dönmesi için oluşturulmuş bir performans optimizasyonu 

  syncronized(SingletionExampleClass.class)

  if null == instance

instance =  new Sing...

       return instance;

tarzı bir yaklaşım ile, layz olarak yaratabilirsiniz, buradaki kod, hem thread safe bir yaklaşım (lock almak volatile olarak instance nesnesini olusturmadığı için çekirdeklerin kendi cachelerinde obje aslında yaratılmıs olabilir, javada syncronized her ikisinide sağlıyor) hemde l1 l2 gibi işlemci cachelerinden kaynaklı birden fazla instance oluşmasını engellemesi için 


===ABSTRACT FACTORY====

* widget tiplerin var ve bu tiplerin içerisinden belirli işlemleri yapacağın methodlar var örneğin içerisindeki productları getir

* bir widget abstract factory widget interface'inden türeyen bir çok farklı widget oluşturabilir


interface widget

getProdcuts()

//widget methodları



class BrowserswipeWidget implements widget


class mobilBrowserWiget implements widget


interface widgetFactory

//burada her factory de olan methodlar



class BrowserwidgetFactory implements widgetFactory

publlic Widget createSwipeWidget() {

return new BrowserWidget() }}


aynısının mobilBrowser içi olanınıda yazabiliriz


client tarafında


new BrowserWidgetFactory

browserWidgetFactory.createSwipeWidget


yada

mobilBrowserWidgetFactory.createSwipeWidget


client istediği yerde nasıl bir widget ile uğraştığını bilmeden yarattığı widgeta


someKindOfWidget.getProducts();

diyerek kullanabilmeli


ProductInterface <-------- factoryInterface

| |

| |

concarateProduct <-------- concarateFactory


=====COMMAND===

!principle of separation of concerns

command interface i var execute içeren
içinde sadece execute içeren method var
bu command interface'ine ait bir slotu bulunan asıl işi yapan objemiz var
o bu slota farklı bir command objesini alıp işlemini yapıypor

concarete clasın belirli özelliklerini kullanan yapılar commandClasları oluyor
ana sınıf bu command interface'inden slotlara sahip oluyor

interface Command//
execute();

ligth //concarate
ligthOnCommand// ligth i kullanan concarate command sınıfı, executeda ligth sınıfını kullanır
Ligth ligth;

execute() { ligth.on(); }

alexa //alexe cihazının main clası
Command commanSlot; //command slot


====STRATEGY=====
* objenın yapabileceklerini extend etmek(!open/close, gelişime açık ama classı degiştirmeden-degişime kapalı-)
* subclasslar ile yapabilirsin ama birden fazla class tanımlaman gerekir ve run time içerisinde bu classları değiştirmen sorunludur
* aslında command DP nin bir formudur ama tek amacı özelliğini extends etmek

obje.setAction(someClass)
//bu sekılde aslında objeye o islemi yapabilecek bir obje geçiyorum
someClass implements myManagerInterface
//burada bu özellikleri barındıran minik classlar var

//eg
obje.productManager.setProduct() 
//hangi tür product manager kullandığından bağımsız o managere özgü product setleme yeteneğini eklemiş oldum



====CHAIN OF RESPONSIBILITY (CoR) ===

compile time de tam olarak ne yapacağın belli olmayan durumlarda kullanabilirsin (RUN TİME DA KARAR VERMEN GEREKEN DURUMLAR)

bir istek geliyor, bu request olabilir bir aksiyon olabilir event olabilir, ama bunun sonucunda ne yapman gerektiğine emin değilsin aslında bu "chain" bir sonraki adıma verip bana bu geldi bunu işleyebilirmisin diye soruyor eğer işleyebileceği bir şey ise zaten devam ettiryior

devredeceğin bilgiyi bir objeye çevirim onu aktarabilirsin, burada handler (yani zincirin bir adımını üstlenen sınıflar) benzer ortak özellikler varise abstract base handler yapabilirsin
her handler ya isteği işler yada bir sonraki adıma devreder

* her işlemi bir sınıf yapacağını için single responsibility prensibine uyar
* open/close mevcut kodu bozmadan yeni bir handler ekleyebilirsin

decaratorden farkı decarator isteği sonuna kadar işleyip base interface e bağlı kalır (genellikle) ama CoR da istek zincirin herhangi bir noktasında sonlanabilir

örneğin;

* bir alışverişi iade ediyoruz, bu iade süresince kişinin cüzdan heasbına aktarım yapabilirsin, direk geri ödeme yapabilirsin yada bankadan para çoktan çekildi ise ödeme talimatı oluşturabilirsin, aslında herhangi bir adımda sonlanabilir

* CoR un bir diğer özelliği işlem sırasını kontrol edebilirsin (hatta runtime da bile bu sırayı belirleyebilirsin)

* her bir handler adımı (zincirin bir adımı) command object olabilir ve tipine göre (kendi instancelarına göre) iadeyi & notificationları & loglama yöntemlerini yönetebilir

Yorumlar

Bu blogdaki popüler yayınlar

Neler Okuyorum ?

Tüketmeme İhtiyacı

Teknik içerik: Neler Okuyorum ?