Giriş
Bir sınıfın davranışını dinamik olarak genişletmek istiyorsanız, alt sınıflarla kalıtımı çoğaltmak yerine Decorator Pattern kullanarak mevcut nesneye ek sorumluluklar ekleyebilirsiniz.
Örneğin; bir loglama servisine Caching, Retry veya Validation gibi ek fonksiyonlar eklemek için ideal bir çözümdür.
1. Decorator Pattern Temel Kavramları
-
Component: Temel arayüz veya soyut sınıf.
-
ConcreteComponent: Asıl işlevi yerine getiren sınıf.
-
Decorator:
Component’i implement eden ve birComponentreferansı tutan sarmalayıcı; ortak soyut base sınıf zorunlu değildir. -
ConcreteDecorator: Ek davranışları uygulayan sınıflar.
2. Decorator Pattern kod örneği
A. Component Arayüzü
public interface IMessage
{
void Send(string content);
}
B. ConcreteComponent
public class EmailMessage : IMessage
{
public void Send(string content)
{
Console.WriteLine($"Email gönderildi: {content}");
}
}
C. Base Decorator
public abstract class MessageDecorator : IMessage
{
protected readonly IMessage _inner;
protected MessageDecorator(IMessage inner) =>
_inner =
inner ?? throw new ArgumentNullException(nameof(inner));
public virtual void Send(string content)
{
_inner.Send(content);
}
}
D. ConcreteDecorator’lar
using System.Text;
public class LoggingDecorator : MessageDecorator
{
public LoggingDecorator(IMessage inner)
: base(inner) { }
public override void Send(string content)
{
ArgumentNullException.ThrowIfNull(content);
Console.WriteLine(
$"[Log] Mesaj gönderiliyor; uzunluk: {content.Length}"
);
base.Send(content);
}
}
public class EncodingDecorator : MessageDecorator
{
public EncodingDecorator(IMessage inner)
: base(inner) { }
public override void Send(string content)
{
var encoded = Convert.ToBase64String(
Encoding.UTF8.GetBytes(content)
);
Console.WriteLine("[Encode] Base64 dönüşümü");
base.Send(encoded);
}
}
E. Kullanım
IMessage email = new EmailMessage();
IMessage loggedEmail = new LoggingDecorator(email);
IMessage encodedLoggedEmail = new EncodingDecorator(loggedEmail);
encodedLoggedEmail.Send("Merhaba Dünya");
// Output:
// [Encode] Base64 dönüşümü
// [Log] Mesaj gönderiliyor; uzunluk: 20
// Email gönderildi: TWVyaGFiYSBEw7xueWE=
3. Decorator Pattern ve katman sınırı
| Katman | Rol |
|---|---|
| Application | IMessage contract’ı ve uygulama davranışları |
| Infrastructure | Gerçek e-posta/encoding/logging adaptörleri; bağımlılıklarına göre yerleştirme |
| API/UI | Decorator zincirini oluşturan yapılandırma kodu |
4. Avantajlar & Dezavantajlar
Avantajlar
-
Esnek Genişletme: İstenilen sayıda decorator ekleyebilirsiniz.
-
Ayrı Sorumluluk: Logging, Encoding gibi davranışlar ayrı sınıflarda.
-
Dinamik Zincir: Çalışma zamanında decorator’ları değiştirebilirsiniz.
Dezavantajlar
-
Çoklu Katman: Derin decorator zinciri kodu izlemeyi zorlaştırabilir.
-
Konfigürasyon Maliyeti: Client’ın dekoratörleri sıralı şekilde oluşturması gerekir.
İleri Okuma ve Kaynaklar
5. Sonuç
Decorator Pattern ile:
-
Mevcut nesneleri bozmadan yeni davranışlar ekleyin.
-
Katmanlı mimaride sorumlulukları net ayırın.
-
Dinamik ve test edilebilir bir genişletme altyapısı oluşturun.
Base64 bir encoding işlemidir; anahtar, gizlilik veya bütünlük koruması sağlamaz. Örnek bu yüzden EncodingDecorator adını kullanır. Convert.ToBase64String belgesi byte’ların string temsiline dönüşümünü açıklar. EmailMessage yalnız console demo’sudur, e-posta göndermez; System.Text using’i sınıf dosyasının başına gelir.
Sıra davranışı değiştirir: dıştaki EncodingDecorator önce dönüştürür, LoggingDecorator encoded metnin uzunluğunu görür. Payload loglamayı varsayılan yapmayın. Retry ekleyeceğiniz mesaj gönderiminde idempotency ve kısmi başarıyı ayrıca tasarlayın; wrapper sayısı güvenilirliği otomatik artırmaz. Karşılaştırma için Chain of Responsibility isteği devretme ve short-circuit akışını açıklar.
Aynı interface’i uygulamak aynı davranış sözleşmesini garanti etmez. Alıcı düz metin bekliyorsa encoding wrapper’ı şeffaf değildir; format üzerinde anlaşma gerekir. Ayrıca inner çağrı exception üretirse başarı log’u yazmayın. Tablo olası bir yerleşimdir: somut e-posta transport’u ve dış servis bağımlılıkları Infrastructure’a aittir, her decorator için tek zorunlu katman yoktur.
