|
Decorater Tasarım Kalıbı : ASP.NET ile Datagrid Örneği |
|
Gönderiliyor lütfen bekleyin... |
|
|
Merhaba, C#nedir?com’da
yayınladığım ilk makalemde sizlere tasarım kalıplarından Decarator
tasarım kalıbını anlatmaya çalışacağım.Basit bir uygulama yaparak bu tasarım kalıbının
pratikte nasıl kullanıldığını göstereceğim.
Tasarım kalıplarına ait genel bilgiyi Singleton
Tasarım Deseni makalesinde bulabilirsiniz. Birkaç gün önce daha önceden
yaptığım bir web projesinin kodlarını gözden geçirip düzenleme(refactoring)
yapıyordum. Projede kullandığım DataGrid kontrollerinin çoğunda silme butonu
kullandığımı fark ettim. Silme butonuna tıklanıldığında javascript kodu yarıdmıyla
ekrana, seçilen kaydın gerçekten silinmesinin istenip istenmediğini soran bir
ileti çıkıyor ve seçimin sonucuna göre gerekli işlem gerçekleştiriliyordu.(şekil
1)
(Şekil 1)
Yukarıda bahsedilen işlemi gerçekleştirebilmek için DataGrid
kontrolünün ItemDataBound olayında ilgili Sil butonunu bularak bu botunun Attributes
özelliğine aşağıdaki gibi ilgili javascript kodu ekliyordum.
private void
dgListe_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs
e)
{
if(e.Item.ItemType==ListItemType.Item
|| e.Item.ItemType==ListItemType.AlternatingItem)
{
e.Item.Cells[6].Attributes.Add("onclick",
"return confirm(’Silmek Istediginizden Emin misiniz?’)");
}
} |
Evet kodumuz bu
haliyle gayet iyi gözüküyor ve işimizi görüyor.Fakat şunu farkettim. Sil butonu
kullanacağımız her datagrid için bu kodu tekrar yazmamız gerekli ve buda kod
tekrarını arttırıyor.Şöyle bir çözüm geliştirdim: DataGrid kontrolünden türeyen
yeni bir DataGrid sınıfı oluşturursam ve türettiğim DataGrid kontrolünün ItemDataBound
olayında yukarda bahsedilen silme işlemi yaparsam bu kodu tekrar tekrar yazmak
zorunda kalmayacaktım.Aşağıda DataGrid kontrolünden türeyen yeni DataGridSilButon
sınıfımızın kodlarını görüyoruz.
public class
DataGridSil: System.Web.UI.WebControls.DataGrid
{
protected int silSutunIndex =-1;
protected bool silOnay =true;
public DataGridSil() { }
public int SilSutunIndex
{
get{return
silSutunIndex ;}
set{silSutunIndex
=value;}
}
public bool SilOnay
{
get { return
silOnay; }
set { silOnay=
value; }
}
protected override void OnItemDataBound(DataGridItemEventArgs e)
{
base.OnItemDataBound
(e);
if ((silOnay==true)
&& (silSutunIndex != -1))
{
e.Item.Cells[silSutunIndex ].Attributes.Add("onclick", "return
confirm(’Silmek Istediginizden Emin misiniz?’)");
}
}
}
|
Yeni türettiğimiz
DataGrid kontrolünü sayfamıza aşağıdaki gibi register ederek kullanabiliyoruz
<%@
Register tagprefix="dg" Namespace="MCA.Web" Assembly="MCA"
%>
.....
<dg:DataGridSilButon id="grid" runat="server" .....
>
<dg:DataGridSilButon>
|
Artık her projede rahatça kullanabileceğimiz "sil butonu" eklenmiş
yeni bir datagrid nesnemiz var. Projemde eski model DataGrid’leri tek tek bu
yeni türettiğim DataGrid ile değiştirirken bazı DataGrid kontrolleri üzerinde
yönlendirme işlemi yaptığım sütunlar bulunduğunu farkettim. Mesela e-mail atma
sütununu çoğu DataGrid konrolünde kullanmışım.
Örnek olarak E-mail sutununa tıkladığımda mail.aspx sayfasına tıkladığım sutunun
mail adresini parametre olarak gönderiyordum.Bunun içinde Sil butonuna benzer
DataGrid kontrolünün ItemDataBound olayına yönlendirme işlemini gerçekleştiren
javascript kodunu ekliyordum. Aklıma hemen bu yaptığım işlemler içinde daha
önce türettiğim DataGridSil sınıfına benzer yeni bir DataGridURL sınıfı türetmek
geldi.Bu yeni sınıfımda yönlendirme yapacağım sutunları belirleyecektim ve ardından
hangi adrese gideceklerini söyleyecektim böylece bu yönlendirme işlemi için
her DataGrid kontrolünün ItemDataBound olayına yazdığım koddan kurtulacaktım.
Gayet iyi bir çözüm
olarak gözüküyordu. Projemde gözden geçirme işlemlerine devam ederken yönlendirme
ve silme işlemlerini bir arada yaptığım DataGrid kontrolleri olduğunu farkettim.
Bu kısma kadar herşey güzel gidiyordu fakat burada biraz kafam karışmıştı.Şimdi
ne yapmam gerekiyordu?Aklıma hemen şöyle bir fikir geldi tekrar 3. bir DataGrid
türetip buna DataGridMailveURL ismini verebilirdim.Bu türettiğim DataGrid’in
ItemDataBound olayında hem silme hemde yönlendirme işlemlerinin ikisini birden
yapabilirdim.Tabi ilerleyen aşamalarda yeni bir özellik kullandığım DataGrid
kontrolü görürsem tekrar yeni bir sınıf türetmem gerekirdi..Aşağıda ilk olarak
düşündüğüm çözümün UML diyagramını görüyorsunuz.
Yukarıda gördüğümüz gibi DataGrid kontrolüne eklediğimiz her yeni özellik için
yeni bir sınıf türetmemiz gerekiyor. Ayrıca eklediğimiz iki özelliğin bir arada
kullanıldığı DataGrid kontrolü için de ayrıca yeni bir sınıf türetmemiz gerekiyor.Örneğin
resim sütunu içeren bir DataGrid kontrolüne ihtiyacımız olsun ve bu resim sütununa
bastığımızda ilgili resmi göstersin.Bunu yapmak için de yeni bir sınıf türetmemiz
gerekir.Ayrıca bu resim özelliği içeren yeni DataGrid kontrolünde silme özelliğini
kullanmak istiyorsak silme ve resim gösterme özelliklerini birarada içeren yeni
bir sınıf türetmemiz gerekir yani kısacası ekleyeceğimiz her özellik için ve
de bu özelliklerden bazılarını bir arada kullanacağımız DataGrid kontrolleri
için yeni sınıflar türetmemiz gerekir böylece kalıtım zinciri uzayıp gider.
İşte takıldığım
bu noktada yardımıma Decorator Tasarım kalıbı yetişti.Kısaca tanımını yaparsak
Decorator tasarım kalıbı bize bir nesneye yeni özellikler eklemek için türetmeyi
kullanarak yeni sınıf oluşturmadan nesneye yeni özellikler eklememize olanak
sağlar. Bu işlemi türetme yenine kompozisyon kullanarak yapar.Bunu adından da
anlaşıldığı gibi dekorasyon işlemi gibi düşünebiliriz.Örneğin elimizde mağazadan
aldığımız bir mutfak dolabı var bu dolabın üstüne bizim extra ihtiyaçlarımız
için yeni bir raf ekletmek istiyoruz bu işlem için dolabı marangoza gönderip
ihtiyacımıza göre yeni bir raf eklettirebiliriz.Böyle olmasaydı dolabı üreten
fabrika bizim extra ihtiyacımız için yeni bir raf içeren dolap kalıbı üretecek
ve ardından bu kalıbı kullanarak dolap üretecek ve bu kalıptan üretilen bütün
dolaplar aynı olacaktı.Tabi bu extra rafı herkesin istemeyebileceğini ya da
herkesin değişik ihtiyaçları olduğunu düşünürsek herkesin ihtiyacı için fabrikanın
ayrı dolap kalıpları üretmesi gerekecekti.Ama biz ekleyeceğimiz extra özelliği
marangoza yaptırarak sorunun üstesinden geldik diyelim ki yarın değişik bir
şey ekletmek istiyorsak tekrar fabrikanın bunun için yeni bir kalıp üretmesini
beklemeden marangoza gönderip tekrar aynı işlemi yaptırabilirz.Örnek biraz garip
oldu ama umarım anladınız:)
Şimdi DataGrid
kontrolümüze Decorator tasarım kalıbını kullanarak tekrar yeni özellikler ekleyelim
ve aradaki farkı görelim. Aşağıda decorator tasarım kalıbına göre tasarladığımız
DataGrid’in UML diyagramı gözükmektedir.
Öncelikle alt sınıflarda kullanacağımız ortak özellikleri soyut DataGridDecorator
sınıfında topluyoruz
public
abstract class DataGridDecorator : System.Web.UI.WebControls.DataGrid
{
protected DataGrid grid;
public DataGridDecorator() { }
public DataGridDecorator(DataGrid Grid)
{
this.grid =Grid;
if(grid != null)
{
grid.ItemDataBound -=new DataGridItemEventHandler(Grid_ItemDataBound);
}
grid =Grid;
grid.ItemDataBound +=new DataGridItemEventHandler(Grid_ItemDataBound);
}
protected abstract void Grid_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs
e);
}
|
Ardından bu sınıftan
türeyen ve de yapıcısına parametre olarak gönderdiğimiz DataGrid kontrolüne
silme özelliği ekleyen yeni decorator sınıfımızı yazalım.
public
class DataGridSil:DataGridDecorator
{
protected
int delcolIndex =-1;
protected
bool confirmdel =true;
public DataGridSil()
{ }
public DataGridSil(DataGrid
Grid):base(Grid) { }
public int
DeleteColumnIndex
{
get{return
delcolIndex;}
set{delcolIndex=value;}
}
public
bool ConfirmOnDelete
{
get{
return confirmdel; }
set
{ confirmdel = value; }
}
protected
override void Grid_ItemDataBound(object sender, System.Web.UI.WebControls.DataGridItemEventArgs
e)
{
base.OnItemDataBound
(e);
if (!confirmdel)
return;
if
(e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem
|| e.Item.ItemType == ListItemType.SelectedItem)
{
if
(delcolIndex != -1)
{
e.Item.Cells[delcolIndex].Attributes.Add("onclick",
"return confirm(’Silmek Istediginizden Emin misiniz?’)");
}
}
}
}
|
Yukarıdaki decorator
sınıfıza benzer şekilde yönlendirme decorator sınıfımızıda yazarız.Burada daha
fazla uzatmamak için yönlendirme işlemi yapan sınıfın kodlarını yazmıyorum örnek
sınıfları ekteki dosyadan indirebilirsiniz. Şimdi de decorator sınıfımızın nasıl
kullanıldığına bakalım. Formumuzda bulunan DataGrid kontrolümüze silme ve yönlendirme
özelliği eklemek için neler yapacağımıza bakalım.
gridByDelete
=new DataGridSil(dgFirmaListe);
gridByDelete.DeleteColumnIndex=6;
gridByURL
=new DataGridURL(dgFirmaListe);
gridByURL.setColumnURL(5,"mail.aspx?adres={5}");
|
Birde decorator
sınıfı oluşturmadan normal türetme yoluyla nasıl yapabilirdik ona bakalım.
//Sadece
silme özelliği içeren DataGrid için
DataGridSil
gridSil =new DataGridSil();
gridSil.DeleteColumnIndex=6;
//Sadece
yönlendirme işlemi yapan DataGrid için
DataGridURL
gridByURL =new DataGridURL();
gridByURL.setColumnURL(5,"mail.aspx?adres={5}");
//Silme ve
yönlendirme işlemi yapan DataGrid için
DataGridSilURL
gridSilURL =new DataGridSilURL();
gridSilURL.setColumnURL(5,"mail.aspx?adres={5}");
gridSilURL.DeleteColumnIndex=6;
|
Gördüğümüz gibi
istediğimiz işlemi decorator sınıfları kullanmadan yapmak için birçok sınıf
türettik ve bu sınıfların hepsini ayrı ayrı kullanmak zorunda kaldık. Fakat
bu işlemi decorator sınıfları kullanarak yapmak için sadece yeni özellik eklemek
istediğimiz nesneyi özelliği içeren decorator sınıfına parametre olarak göndermemiz
yeterli.Ayrıca bu özellikten başka değişik bir özellik eklemek için yine aynı
nesneyi o özelliği içeren decorator sınıfına parametre olarak göndererek kolayca
yapabiliyoruz.
Umarım ilk makalem
sizlere faydalı olmuştur. Elimden geldiğince Tasarım kalıpları ile alakalı gerçek
uygulamalarda karşılaşılan problemleri örneklerle anlatmaya çalışacağım. Birdahaki
yazımda Observer Tasarım kalıbını ufak bir örnekle anlatmaya çalışacağım.Hepinize
iyi çalışmalar.
Örnek
sınıfları buradan indirebilirsiniz.
Makale:
Decorater Tasarım Kalıbı : ASP.NET ile Datagrid Örneği C#, Visual C# ve .NET Cihat Altuntaş
|
|
|
-
-
Eklenen Son 10
-
Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor
|
|