Command Design Pattern
Yazılım geliştirmede bazen bir işlemi sadece “yapmak” yetmez; o işlemi sıraya koymak, geri almak (undo), loglamak veya daha sonra çalıştırılmak üzere saklamak istersiniz. İşte tam bu noktada, bir metodun çağrılmasından fazlasına, o çağrının kendisine bir “nesne” olarak muamele etmeye ihtiyaç duyarsınız.
Bugün, Behavioral (Davranışsal) tasarım desenlerinin en güçlülerinden biri olan Command Pattern’ı ve onu kardeşlerinden ayıran ince çizgileri masaya yatırıyoruz.
Command Pattern Nedir? (Restoran Analojisi)
En klasik ama en iyi anlaşılan örnekle başlayalım: Bir restoran.
Siz (Client) masaya oturursunuz ve bir sipariş verirsiniz. Garson (Invoker), siparişinizi alır ve bir kağıda yazar (Command). Garson, yemeği nasıl yapacağını bilmez; o sadece siparişi (kağıdı) mutfağa, yani şefe (Receiver) iletir.
Eğer Command pattern olmasaydı, mutfağa gidip şefe bizzat “Domatesleri kes, tavayı ısıt” demeniz gerekirdi. Command Pattern, isteği yapan (Siz) ile isteği yerine getireni (Şef) birbirinden ayırır. Aradaki “Sipariş Fişi” (Command Nesnesi), ne yapılması gerektiği bilgisini taşır.
Get Muratguven’s stories in your inbox
Join Medium for free to get updates from this writer.
Teknik Tanım: Command Pattern, bir isteği (request) bir nesne olarak kapsüller. Bu sayede istemcileri farklı isteklerle parametreleyebilir, istekleri kuyruğa alabilir veya loglayabilir ve geri alınabilir (undoable) işlemler yapabilirsiniz.
Kod Üzerinden Bakış
Basit bir akıllı ev sistemi düşünelim. Işığı açmak bir komuttur.
- Command Arayüzü (Sipariş Fişi Şablonu) Tüm komutların uyması gereken tek bir kural vardır:
Execute(Çalıştır).
public interface ICommand
{
void Execute();
void Undo();
}2. Receiver (Şef / Işık) İşi gerçekten yapan birim.
public class Light
{
public void TurnOn() => Console.WriteLine("Işık açıldı.");
public void TurnOff() => Console.WriteLine("Işık kapandı.");
}3. Concrete Command (Somut Sipariş) Komutun kime (hangi ışığa) ve ne şekilde uygulanacağını bağlayan sınıf.
public class TurnOnLightCommand : ICommand
{
private Light _light;
public TurnOnLightCommand(Light light)
{
_light = light;
}
public void Execute()
{
_light.TurnOn();
}
public void Undo()
{
_light.TurnOff();
}
}4. Invoker (Garson / Kumanda) Komutu tetikleyen ama işin detayını bilmeyen birim.
public class RemoteControl
{
private ICommand _command;
public void SetCommand(ICommand command)
{
_command = command;
}
public void PressButton()
{
_command.Execute();
}
}Kritik Bölüm: Benzer Desenlerden Farkı Nedir?
Command Pattern genellikle Strategy, Chain of Responsibility ve Memento ile karıştırılır veya birlikte kullanılır. Aradaki farkları anlamak, deseni doğru yerde kullanmanızı sağlar.
1. Command vs. Strategy
Bu ikisi yapısal olarak çok benzer görünür ama niyetleri tamamen farklıdır.
- Strategy Pattern: “Nasıl?” sorusuna odaklanır. Aynı işi yapan farklı algoritmalar sunar. (Örn: A noktasından B noktasına gitmek için Yürüyerek, Arabayla veya Bisikletle gitme stratejileri).
- Command Pattern: “Ne?” sorusuna odaklanır. Yapılacak işi bir nesneye dönüştürür. Amacı algoritma seçmek değil, işlemi geciktirmek, kuyruğa sokmak veya geri almaktır.
- Özet: Strategy, eylemin nasıl yapılacağını değiştirir; Command, eylemin kendisini bir pakete dönüştürür.
2. Command vs. Chain of Responsibility (CoR)
Her ikisi de gönderici ve alıcıyı ayırır (decoupling), ama yöntemleri farklıdır.
- CoR: İsteği bir zincir boyunca iletir. Zincirdeki nesnelerden biri “Ben bunu halledebilirim” diyene kadar istek dolaşır. İsteği kimin karşılayacağı dinamiktir.
- Command: İstek, belirli bir alıcıya (Receiver) zaten bağlanmış bir nesnedir. Genellikle tek bir yere gider ve orada çalıştırılır.
3. Command vs. Memento
Genellikle birlikte kullanılırlar ama görevleri ayrıdır.
- Memento: Bir nesnenin o anki durumunu (state) kaydeder.
- Command: Bir nesnenin üzerindeki işlemi (operation) temsil eder.
- Birlikte Kullanımı: Kusursuz bir “Undo” (Geri Al) mekanizması için; Command işlemi tetikler, Memento ise işlem yapılmadan önceki durum
Ne Zaman Kullanmalısın?
- Undo/Redo (Geri Al/Yinele) Gerekiyorsa: Photoshop gibi uygulamalardaki her işlem bir
Commandnesnesidir. Geçmişe dönmek, bir önceki komutunUndometodunu çağırmaktan ibarettir. - Task Scheduling (Zamanlanmış Görevler): Komutları bir listeye (Queue) atıp, sırayla veya belirli bir saatte çalıştırmak istiyorsanız (Job Queue sistemleri).
- Makro Kaydı: Kullanıcının yaptığı işlemleri sırayla kaydedip daha sonra tek tuşla hepsini tekrar oynatmak istiyorsanız.
Sonuç
Command Pattern, kodunuzdaki “eylemleri” birinci sınıf vatandaş (first-class citizens) haline getirir. Artık metodunuz sadece bir kod bloğu değil, saklanabilir, taşınabilir ve yönetilebilir bir nesnedir. Eğer projenizde işlemlerin geçmişini tutmanız veya işlemleri asenkron olarak kuyruklamanız gerekiyorsa, aradığınız kahraman muhtemelen Command Pattern’dır.





