C# Dilinde Tasarım Desenleri: Kapsamlı Bir Rehber

Tasarım Desenleri Nedir?

Tasarım desenleri, yazılım geliştirme süreçlerinde sıkça karşılaşılan sorunları çözmek için oluşturulmuş, tekrar kullanılabilir çözümler sunan yapısal yöntemlerdir. 1994 yılında Erich Gamma, Richard Helm, Ralph Johnson ve John Vlissides tarafından yazılan "Design Patterns: Elements of Reusable Object-Oriented Software" adlı kitap ile resmi hale gelen bu desenler, yazılım dünyasında yaygın olarak kullanılmaktadır. Bu dört yazılım mühendisinin oluşturduğu gruba "Gang of Four (GoF)" denir.

Tasarım desenleri genel olarak üç ana kategoriye ayrılır:

  1. Yaratıcı (Creational) Desenler
  2. Yapısal (Structural) Desenler
  3. Davranışsal (Behavioral) Desenler

Tasarım Desenlerinin Kategorilerine Göre Tam Liste:

1. Yaratıcı (Creational) Desenler:

  • Singleton
  • Factory Method
  • Abstract Factory
  • Builder
  • Prototype

2. Yapısal (Structural) Desenler:

  • Adapter
  • Bridge
  • Composite
  • Decorator
  • Facade
  • Flyweight
  • Proxy

3. Davranışsal (Behavioral) Desenler:

  • Chain of Responsibility
  • Command
  • Interpreter
  • Iterator
  • Mediator
  • Memento
  • Observer
  • State
  • Strategy
  • Template Method
  • Visitor

C# Dilinde En Çok Kullanılan Tasarım Desenleri

1. Singleton Design Pattern

Amaç: Bir sınıftan sadece bir örnek (instance) yaratılmasını sağlar. Bu, genellikle sınıfın global bir erişim noktasına sahip olması gerektiği durumlarda kullanılır.

Örnek Kullanım: Genellikle loglama, konfigürasyon yönetimi ve veritabanı bağlantısı gibi global erişim gerektiren yapılarda kullanılır.

C# Kod Örneği:

public class Singleton
{
    private static Singleton _instance;
    private static readonly object _lock = new object();

    private Singleton() { }

    public static Singleton Instance
    {
        get
        {
            lock (_lock)
            {
                if (_instance == null)
                {
                    _instance = new Singleton();
                }
                return _instance;
            }
        }
    }

    public void LogMessage(string message)
    {
        Console.WriteLine(message);
    }
}


Proje Deneyimi:

Bir e-ticaret uygulamasında veritabanı bağlantısını tek bir global erişim noktası üzerinden yönetmek gerektiğinde, Singleton deseni kullanılmıştır. Bu, performans iyileştirmesi sağlamış ve aynı zamanda yönetimi kolaylaştırmıştır.

2. Factory Design Pattern

Amaç: Bir sınıfın oluşturulmasını alt sınıflarına bırakarak, nesnelerin hangi sınıfa ait olduğunun belirlenmesini sağlar. Bu desen, aynı arayüzü kullanan farklı sınıfların dinamik olarak oluşturulmasında kullanılır.

Örnek Kullanım: Farklı veri tabanı sağlayıcıları (SQL, MongoDB, Oracle) veya ödeme sistemleri (kredi kartı, PayPal) ile çalışırken tercih edilir.

C# Kod Örneği:

public abstract class Database
{
    public abstract void Connect();
}

public class SqlDatabase : Database
{
    public override void Connect()
    {
        Console.WriteLine("SQL Database connected.");
    }
}

public class MongoDatabase : Database
{
    public override void Connect()
    {
        Console.WriteLine("MongoDB connected.");
    }
}

public class DatabaseFactory
{
    public static Database CreateDatabase(string type)
    {
        if (type == "SQL")
            return new SqlDatabase();
        else if (type == "MongoDB")
            return new MongoDatabase();
        else
            throw new ArgumentException("Invalid type.");
    }
}


Proje Deneyimi:

Bir CMS (Content Management System) projesinde, farklı veritabanı yönetimi ihtiyacı için Factory deseni kullanılmıştır. Sistem hem SQL hem de MongoDB desteği sağlayarak kullanıcı tercihlerine göre esnek yapı sunmuştur.

3. Observer Design Pattern

Amaç: Bir nesne değiştiğinde, ona bağlı diğer nesnelere haber verir. Bu desen, bir nesnenin durum değişikliğinde diğer ilgili nesneleri otomatik olarak güncelleyerek kullanılır.

Örnek Kullanım: Yayın/abone (publish/subscribe) sistemlerinde, sosyal medya bildirimleri, stok değişikliği gibi durumlarda sıkça kullanılır.

C# Kod Örneği:

public interface IObserver
{
    void Update(string message);
}

public class Follower : IObserver
{
    public string Name { get; set; }

    public Follower(string name)
    {
        Name = name;
    }

    public void Update(string message)
    {
        Console.WriteLine($"{Name} received notification: {message}");
    }
}

public class Celebrity
{
    private List<IObserver> _followers = new List<IObserver>();

    public void AddFollower(IObserver observer)
    {
        _followers.Add(observer);
    }

    public void RemoveFollower(IObserver observer)
    {
        _followers.Remove(observer);
    }

    public void NotifyFollowers(string message)
    {
        foreach (var follower in _followers)
        {
            follower.Update(message);
        }
    }
}


Proje Deneyimi:

Bir online mağazada ürün fiyat değişikliklerini müşterilere bildirmek için Observer deseni kullanılmıştır. Müşteriler, ilgilendikleri ürünlerin fiyat düşüşlerinden anında haberdar olmuş ve satışlar artmıştır.

4. Strategy Design Pattern

Amaç: Bir işlemi gerçekleştirmek için birden fazla algoritma sağlar ve bu algoritmaları gerektiğinde değiştirir. Kullanıcıya farklı stratejiler arasında seçim yapma imkânı verir.

Örnek Kullanım: Farklı ödeme sistemleri ile ödeme süreçlerini yönetmek ya da farklı sıralama algoritmalarını uygulamak için kullanılır.

C# Kod Örneği:

public interface IPaymentStrategy
{
    void Pay(double amount);
}

public class CreditCardPayment : IPaymentStrategy
{
    public void Pay(double amount)
    {
        Console.WriteLine($"Paid {amount} using Credit Card.");
    }
}

public class PayPalPayment : IPaymentStrategy
{
    public void Pay(double amount)
    {
        Console.WriteLine($"Paid {amount} using PayPal.");
    }
}

public class PaymentContext
{
    private IPaymentStrategy _paymentStrategy;

    public void SetPaymentStrategy(IPaymentStrategy paymentStrategy)
    {
        _paymentStrategy = paymentStrategy;
    }

    public void MakePayment(double amount)
    {
        _paymentStrategy.Pay(amount);
    }
}


Proje Deneyimi:

Bir e-ticaret platformunda, müşterilere farklı ödeme yöntemleri sunmak için Strategy deseni kullanılmıştır. Kredi kartı, PayPal gibi ödeme seçenekleri arasındaki geçişler kolayca yönetilmiştir.

5. Decorator Design Pattern

Amaç: Bir nesneye dinamik olarak yeni işlevler eklemek için kullanılır. Mevcut nesnenin işlevselliğini değiştirmeden yeni özellikler ekler.

Örnek Kullanım: Kullanıcı arayüzü bileşenlerine yeni özellikler eklemek, loglama veya yetkilendirme eklemek için kullanılır.

C# Kod Örneği:

public interface IWidget
{
    void Draw();
}

public class TextBox : IWidget
{
    public void Draw()
    {
        Console.WriteLine("Drawing a TextBox.");
    }
}

public class BorderDecorator : IWidget
{
    private IWidget _widget;

    public BorderDecorator(IWidget widget)
    {
        _widget = widget;
    }

    public void Draw()
    {
        _widget.Draw();
        Console.WriteLine("Adding a border.");
    }
}


Proje Deneyimi:

Bir CRM uygulamasında, arayüze ek özellikler kazandırmak için Decorator deseni kullanılmıştır. Bu sayede mevcut bileşenlerin işlevselliği korunarak yeni özellikler (örneğin, tema desteği) eklenmiştir.

Sonuç:

Tasarım desenleri, C# dilinde yazılım geliştirme sürecinde yaygın olarak kullanılan ve yazılımcılara büyük esneklik sağlayan çözümler sunar. Bu makalede, en sık kullanılan tasarım desenlerinden Singleton, Factory, Observer, Strategy ve Decorator desenlerine dair detaylı örnekler sunduk. Her bir tasarım deseni, yazılımın esnek, sürdürülebilir ve genişletilebilir olmasını sağlamak için kritik öneme sahiptir.