Decorator Pattern - Saat Kac Saat ?
Posted by: sadettinpolat in Tasarim Kaliplari, Uncategorized, delphi, kod ornekleri, oopBir nesneye, nesneyi değiştirmeden yeni sorumluluklar eklenmesini sağlar. Alt sınıflama yapmadan nesnelerin işlevlerinin geliştirilmesini olası kılar.
Elimizde varolan bir sinifa yeni ozellikler eklemek istedigimizi dusunelim. Aklimiza gelen ilk cozum elimizde varolan siniftan istedigimiz ozelliklere sahip yeni bir sinif olusturmak olur. Bircok durumda bu dogru ve gecerli bir yoldur ama bazi durumlarda kas yapayim derken goz cikartabilirsiniz. Bir diger yol ise varolan sinifa hic dokunmadan yeni tanimlanacak baska bir sinif sayesinde eldeki sinifin ozelliklerini istenilen duzeye getirmektir.
Mesela soyle bir ornekle aciklamaya calisayim. Saat uretimi yapan bir fabrikada belirtilen paremetrelere uygun olarak saat uretimi yapan bir makineye program yazmak istediginizi dusunun. Uretimini yapabileceginiz saat tipleri su sekilde olsun.
Calar saat
Duvar saati
Kol Saati
Cep saati
Bu saatlerin analog, dijital, hem analog hem de dijital cesitlerinin oldugunu dusunelim. Bu durumda olusturulacak sinif hiyerarsisi yaklasik olarak soyle olabilir.
Saat
Saat –> Analog Saat
Saat –> Dijital Saat
AnalogSaat –> AnalogDijitalSaat
AnalogSaat –> AnalogCalarSaat
AnalogSaat –> AnalogDuvarSaati
AnalogSaat –> AnalogKolSaati
AnalogSaat –> AnalogCepSaati
DijitalSaat –> DijitalCalarSaat
DijitalSaat –> DijitalDuvarSaati
DijiralSaat –> DijitalKolSaati
DijitalSaat –> DijitalCepSaati
AnalogDijitalSaat –> AnalogDijitalCalarSaat
AnalogDijitalSaat –> AnalogDijitalDuvarSaati
AnalogDijitalSaat –> AnalogDijitalKolSaati
AnalogDijitalSaat –> AnalogDijitalCepSaati
Istedigimiz siniflari olusturabilmek icin 16 ayri sinif tanimlamak zorunda kaldik. Hangi saatten uretmek istiyorsak bu 16 siniftan uygun olan sinifi kullanip makinenin saat uretmesini gerceklestirebiliriz. Hersey iyi guzel ama sinif sayisi gercekten cok fazla gibi. Basitlik ana hedefimiz olmali. Alti ustu saat uretecegiz. Ilerde olabilecek degisikliklerden en az etkilenecek sekilde sistemi tasarlamak bizim yararimiza olacaktir. Yukarida ki listenin kalabalik olmasinin nedeni nedir sorusunu kendimize sordugumuz zaman cevap acik ve nettir. Her saatin Analog, dijital ve hem analog hem de dijital cesitlerinin olmasidir. Eger analog ve Digital ozelliklerini degisik bir yolla saat sinifina uygulayabilirsek bu kalabaligi onemli bir olcude azaltabiliriz.
Bunu nasil yapabiliriz ?
Kume islemlerini hepimiz biliriz. Istedigimiz elemanlari kumeye ekleyip istemediklerimizi cikartiriz. Tipki toplama yapar gibi isimize lazim olan ogeleri kumeye ekleyerek sonuca ulasiriz. Benzer bir olayi burda da kullanarak bircok sinif tanimlamaktan kendimizi kurtarabiliriz. Temel sinifimizin uzerine elimizdeki dekorasyon amacli sinif yada siniflari giydirmek suretiyle elde etmek istedigimiz siniflari olusturabiliriz.
Simdi bu dekorasyon olayini saat ornegimize nasil uygulayabilecegimizi gorelim.
SoyutSaat
SoyutSaat –> DecoratorSinif
SoyutSaat –> Saat
Saat –> CalarSaat
Saat –> DuvarSaati
Saat –> KolSaati
Saat –> CepSaati
DecoratorSinif –> AnalogSaat
DecoratorSinif –> DijitalSaat
Sadece 9 sinif tanimladik. Bu dokuz sinifi ihtiyacimiz olan sekilde kullanarak istedigimiz ozelliklere sahip saatleri olusturmamiz artik cok kolay. Yapmamiz gereken tek sey istedigimiz dekorasyon siniflarini saat sinifimizin uzerine giydirmek. Elimizde artik Canli olarak niteleyebilecegimiz dekorasyon siniflarimiz var.
Decorator siniflari sayesinde Analog bir kol Saati olusturmak istersek soyle bir kod yazmak bizim isimizi gorecektir.
Saat := TKolSaati.Create(TAnalogSaat.Create(TSaat.Create));
ya da hem analog hem de dijital bir duvar saati yapmak isteyelim. iste ornek kodumuz.
Saat := TDuvarSaati.Create(TAnalogSaat.Create(TDijitalSaat.Create(TSaat.Create)));
decorator sinifini tanimladigimiz unit.
unit Unit1;
interface
uses SysUtils;
type
TAbstractSaat = class
Public
procedure SaatKac();virtual;abstract;
End;
TSaat = Class(TAbstractSaat)
public
procedure SaatKac();override;
end;
TDecoratorSaat = class(TAbstractSaat)
private
fSaat:TAbstractSaat;
public
procedure SaatKac();override;
constructor Create(aSaat:TAbstractSaat);
destructor Destroy;override;
end;
TAnalogSaat = class(TDecoratorSaat)
public
procedure SaatKac();override;
end;
TDijitalSaat = class(TDecoratorSaat)
public
procedure SaatKac();override;
end;
TCalarSaat = class(TDecoratorSaat)
public
procedure SaatKac();override;
end;
TDuvarSaati = class(TDecoratorSaat)
public
procedure SaatKac();override;
end;
TKolSaati = class(TDecoratorSaat)
public
procedure SaatKac();override;
end;
TCepSaati = class(TDecoratorSaat)
public
procedure SaatKac();override;
end;
implementation
{ TSaat }
procedure TSaat.SaatKac;
begin
writeln('Saat:' + TimeToStr(Now));
end;
{ TDecoratorSaat }
constructor TDecoratorSaat.Create(aSaat: TAbstractSaat);
begin
fSaat := aSaat;
end;
destructor TDecoratorSaat.Destroy;
begin
FreeAndNil(fSaat);
//Writeln(Self.ClassName);
inherited;
end;
procedure TDecoratorSaat.SaatKac;
begin
if Assigned(fSaat) then
fSaat.SaatKac;
end;
{ TAnalogSaat }
procedure TAnalogSaat.SaatKac;
begin
inherited;
Writeln('Bu bir analog saattir...');
end;
{ TDijitalSaat }
procedure TDijitalSaat.SaatKac;
begin
inherited;
Writeln('Bu bir dijital saattir...');
end;
{ TCalarSaat }
procedure TCalarSaat.SaatKac;
begin
inherited;
Writeln('Bu bir calar saattir...');
end;
{ TDuvarSaati }
procedure TDuvarSaati.SaatKac;
begin
inherited;
Writeln('Bu bir duvar saatidir...');
end;
{ TKolSaati }
procedure TKolSaati.SaatKac;
begin
inherited;
Writeln('Bu bir kol saatidir...');
end;
{ TCepSaati }
procedure TCepSaati.SaatKac;
begin
inherited;
Writeln('Bu bir cep saatidir....');
end;
end.
bu da consol uygulamamiz.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
Unit1 in 'Unit1.pas';
var
Saat:TAbstractSaat;
begin
Saat := TDuvarSaati.Create(TAnalogSaat.Create(TDijitalSaat.Create(TSaat.Create)));
Saat.SaatKac;
FreeAndNil(Saat);
Readln;
end.
ornegi calistirdiginizda consol ciktisi soyle olacaktir.
Saat:21:45:00
Bu bir dijital saattir...
Bu bir analog saattir...
Bu bir duvar saatidir...
Ornegimizde olmazsa olmaz isi yapan TSaat sinifimizdir. TSaat sinifi butun saatlerin yapmasi gereken isi yapmaktadir. Yani saati gostermektedir. Diger siniflar ise saatin kac oldugunu, nerden ogrenebileceklerini bilmezler. Onlar sadece saatin gorunumuyle ilgilenirler ve saatin kac oldugunu TSaat sinifi sayesinde bizlere gosterirler. Kisaca eger sinif hiyerarsiniz cok karmasik bir sekle geliyorsa ve daha basit bir hiyerarsiye ihtiyaciniz varsa ya da asil sinif uzerinde herhangi bir degisiklik ya da turetme yapmadan ilgili sinifa yeni ozellikler eklemek istiyorsaniz Decorator kalibini kullanabilirsiniz. Aslinda Delphi 2005 ile birlikte aslolan sinifa dokunmadan onun ozelliklerini degistirebileceginiz Class Helpers ler mevcut ama bu ozelligi basiniz cok sikisirsa kullanmayi tercih etmelisiniz.
CSharpNedir.com adresinde Decorator kalibi anlatilirken Pizza ornegi verilmisti. Cok cesitli malzemelerden olusabilen pizza icin bir suru decorator sinif tanimlanmisti. Dusunce olarak dogru olsada pratikte sorunun cozumu olarak decorator kalibini kullanmak verilen pizza orneginde cokta kullanisli gelmiyor bana. Cunku pizza da kullanilabilecek bir cok malzeme var ve her malzeme icin ayri bir sinif tanimlamak ya da decorator sinif tanimlamak bakimi gelistirmesi guncellemesi zor olan kodlara neden olur. Bu tip durumlarda Pizza sinifina bir Collection eklemek ve pizza da kullanilacak malzemeleri bu alanda tutmak cok daha guzel bir cozum olur.
Aslına bakarsaniz decorator kalibina simdiye kadar hic ihtiyac duymadim sanirim. Soyle bir eskiye dogru yazdigim kodlari dusundum de “hiimmm! surasi aslinda tam da decorator kalibini kullanabilecegim bir yermis.” dusuncesi hic olusmadi bende. Ya hafizam cok zayif ya da grcekten boyle bir sinif yapisi kurmak gibi bir zorunlulugum simdiye kadar hic olmadi. Saat ornegi pizza ornegi iyi guzel ama daha somut bir ornek, uygulama alani yok mu diye dusunenlere javanin i/o paketinin bu kalibi oldukca cok kullandigini soyleyebilirim. Javada FileWriter sinifi bilgisayardaki fiziksel bir dosyaya baglanti kurarak dosyaya program vasitasiyla veri yazmak icin tasarlanmis bir siniftir. Dosyaya her defasinda bir byte veri yazmanin zaman kaybi oldugunu dusunen gelistiriciler dosyaya bir defada onlarca byte i bir hamlede yazabilecek buffer ozelligi olan BufferedWriter adli bir sinif gelistirmislerdir. BufferedWriter sinifi tamponladigi verileri kendisine parametre olarak gecilen FileWriter nesnesi sayesinde fiziksel olarak dosyaya yazar. Tamponlama da yetmemis bu sefer verileri belirli bir formatta dosyaya yazdirabilmek icin PrintWriter adli bir sinif gelistirmisler. Bu sinifta verileri belirlenen formatta dosyaya yazmaktadir. PrintWriter de tipki BufferedWriter sinifinda oldugu gibi formatlanan verileri dosyaya yazabilemk icin FileWriter adli bir parametre almalidir. İsterseniz sadece tamponlama kullanarak verilerinizi dosyaya yazabilirsiniz.
new BufferedWriter(new FileWriter)
isterseniz formatlanmis verilerinizi dosyaya yazabilirsiniz
new PrintWriter(new FileWriter)
ya da formatlanmis verilerinizi tamponlama kullanarak dosyaya yazabilirsiniz.
new PrintWriter(new BufferedWriter(new FileWriter))
FileWriter sinifi verileri nasil tamponlayacagini ya da nasil formatlandiracagini bilmez. Bildigi tek sey kendisine verilen verileri fiziksel olarak dosyaya yazmaktir. Ayni sekilde BufferedWriter sinifida elindeki verileri nasil dosyaya yazacagini bilmez. Bildigi tek sey elindeki verileri tamponlamaktir. PrintWriter sinifi da sadece verileri formatlamayi bilir ama uc sinifi decorator kalibi esliginde formatlanmis verileri tamponlama kullanarak fiziksel dosyaya yazabilirsiniz.
asim: abi saat neden 21:45 ? bi yerlere gonderme mi yapiyorsun ?
ben: asim ortaligi bulandirma.
asim: abi bulandirma dedin de aklima geldi. evde bunaldim ben. cok sicak hava. birak su dekorasyon, saat kac, 21:45 islerini de disari cikip biraz gezelim.
ben: tamam asim. sabirli ol biraz. bitti. cikariz birazdan.
asim: abi hep nesnelere biseler giydiriyosun. disari cikalimda senin de ustune giyebilecegin bi tisort alalim ne diyorsun ?
ben: su bardak kafanda nasil durur sence asim ? hem biraz da serinlemis olursun.
asim: tamam sustum abi.

Entries (RSS)
August 3rd, 2007 at 01:06:46
[...] patterns Adapter Bridge Composite Decorator Façade Flyweight [...]