Elbette, Command tasarım desenini basitçe açıklayalım ve Java örneğiyle destekleyelim:
Command Tasarım Deseni Nedir?
Command deseni, bir isteği (komutu) bir nesne olarak kapsüller. Bu, istemcilerin farklı istekleri, kuyrukları veya günlükleri parametre olarak göndermesine ve ayrıca geri alınabilir işlemleri desteklemesine olanak tanır.
Neden Kullanılır?
İşlemleri ve onları çağıran nesneleri ayırmak istediğinizde.
İşlem sırasını veya günlüğünü tutmak istediğinizde.
Geri alınabilir işlemler yapmak istediğinizde.
Basit Bir Java Örneği:
Command Arayüzü: Tüm komutların uygulayacağı bir arayüz.
java
Copy code
public interface Command {
void execute();
}
Concrete Command: Gerçekleştirmek istediğiniz işlem.
java
Copy code
public class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.on();
}
}
Receiver: Komutun gerçekleştirileceği nesne.
java
Copy code
public class Light {
public void on() {
System.out.println("Işık açık!");
}
public void off() {
System.out.println("Işık kapalı!");
}
}
Invoker: Komutu çağıran ve ne zaman uygulanacağını belirleyen nesne.
java
Copy code
public class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
Client: Uygulama.
java
Copy code
public class CommandPatternDemo {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
RemoteControl control = new RemoteControl();
control.setCommand(lightOn);
control.pressButton();
}
}
Nasıl Çalışır?
CommandPatternDemo (istemci), bir Light (receiver) nesnesi oluşturur.
LightOnCommand (concrete command) nesnesi, Light nesnesini alır.
RemoteControl (invoker), komutu alır ve tetiklendiğinde execute metodunu çağırır.
Bu, Light nesnesindeki on metodunun çağrılmasına neden olur ve "Işık açık!" mesajı yazdırılır.
Bu örnek, Command deseninin temel yapısını ve nasıl kullanılacağını gösterir. Gerçek dünya uygulamalarında, bu desen daha karmaşık senaryolar için genişletilebilir.
Bana başka basit bir senaryo daha verir misin? Bu deseni uygulayalarak ne gibi avantajlar sağlarız?
Tabii ki, başka bir basit senaryo verebilirim ve Command deseninin sağladığı avantajlardan bahsedebilirim.
Basit Senaryo: Müzik Çalar Kontrolü
Bu senaryoda, bir müzik çaların temel fonksiyonlarını (çalmak, durdurmak) kontrol eden bir uygulama düşünün.
Command Arayüzü:
java
Copy code
public interface Command {
void execute();
}
Concrete Commands:
Müziği Çalmak için:
java
Copy code
public class PlayMusicCommand implements Command {
private MusicPlayer musicPlayer;
public PlayMusicCommand(MusicPlayer musicPlayer) {
this.musicPlayer = musicPlayer;
}
@Override
public void execute() {
musicPlayer.play();
}
}
Müziği Durdurmak için:
java
Copy code
public class StopMusicCommand implements Command {
private MusicPlayer musicPlayer;
public StopMusicCommand(MusicPlayer musicPlayer) {
this.musicPlayer = musicPlayer;
}
@Override
public void execute() {
musicPlayer.stop();
}
}
Receiver (Müzik Çalar):
java
Copy code
public class MusicPlayer {
public void play() {
System.out.println("Müzik çalıyor...");
}
public void stop() {
System.out.println("Müzik durduruldu.");
}
}
Invoker (Uzaktan Kumanda):
java
Copy code
public class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
Client (Uygulama):
java
Copy code
public class MusicPlayerDemo {
public static void main(String[] args) {
MusicPlayer player = new MusicPlayer();
Command play = new PlayMusicCommand(player);
Command stop = new StopMusicCommand(player);
RemoteControl remote = new RemoteControl();
remote.setCommand(play);
remote.pressButton(); // Müzik çalıyor...
remote.setCommand(stop);
remote.pressButton(); // Müzik durduruldu.
}
}
Command Deseninin Avantajları
Soyutlama ve Esneklik: İşlemler, komut nesneleri aracılığıyla soyutlanır. Bu, farklı komutları değiştirebilir, ekleyebilir veya çıkarabilirsiniz, kodun geri kalan kısmına etki etmeden.
Düşük Bağlantılılık (Coupling): İşlemleri gerçekleştiren nesneler ile bu işlemleri çağıran nesneler arasında sıkı bir bağlantı yoktur. Bu, uygulamanın bakımını ve genişletilmesini kolaylaştırır.
Geri Alma / İptal İşlemleri: Komutların geri alınması veya iptal edilmesi işlevselliği kolayca ekleyebilirsiniz. Örneğin, bir "Undo" komutu uygulayarak en son gerçekleştirilen işlemi geri alabilirsiniz.
Komutların Kaydedilmesi ve Yeniden Çalıştırılması: Komutları kaydedip daha sonra tekrar çalıştırabilirsiniz. Bu, özellikle makro kaydı gibi özellikler için kullanışlıdır.
Geliştirilebilirlik: Yeni komutlar eklemek kolaydır ve mevcut kodu değiştirmenize gerek yoktur. Bu, yazılımın genişletilebilirliğini artırır.
Bu senaryo ve avantajlar, Command deseninin neden popüler ve güçlü bir tasarım deseni olduğunu göstermektedir. Özellikle kullanıcı arayüzleri, işlem kuyrukları, ve geri alınabilir işlemler gibi alanlarda oldukça etkilidir.
Son örnek için undo örneği verir misin?
Elbette, müzik çalar senaryosuna bir "geri al" (undo) özelliği ekleyerek Command desenini nasıl genişletebileceğimizi gösterebilirim. Bu örnekte, her komutun son eylemini geri alacak bir mekanizma ekleyeceğim.
Geliştirilmiş Command Arayüzü
Öncelikle Command arayüzüne bir undo metodunu ekleyelim:
java
Copy code
public interface Command {
void execute();
void undo();
}
Concrete Commands'ın Güncellenmesi
Her komut için, execute metoduna ek olarak bir undo metodu ekleyin. Örneğin, PlayMusicCommand ve StopMusicCommand için:
java
Copy code
public class PlayMusicCommand implements Command {
private MusicPlayer musicPlayer;
public PlayMusicCommand(MusicPlayer musicPlayer) {
this.musicPlayer = musicPlayer;
}
@Override
public void execute() {
musicPlayer.play();
}
@Override
public void undo() {
musicPlayer.stop();
}
}
public class StopMusicCommand implements Command {
private MusicPlayer musicPlayer;
public StopMusicCommand(MusicPlayer musicPlayer) {
this.musicPlayer = musicPlayer;
}
@Override
public void execute() {
musicPlayer.stop();
}
@Override
public void undo() {
musicPlayer.play();
}
}
Invoker'da Değişiklikler
RemoteControl sınıfında, en son çalıştırılan komutu saklayıp, undo fonksiyonunu çağıracak şekilde güncelleyelim:
java
Copy code
public class RemoteControl {
private Command command;
private Command lastCommand;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
lastCommand = command;
}
public void pressUndo() {
if (lastCommand != null) {
lastCommand.undo();
}
}
}
Client (Uygulama)
Müzik çalar örneğinde, komutları çalıştırın ve ardından geri alın:
java
Copy code
public class MusicPlayerDemo {
public static void main(String[] args) {
MusicPlayer player = new MusicPlayer();
Command play = new PlayMusicCommand(player);
Command stop = new StopMusicCommand(player);
RemoteControl remote = new RemoteControl();
// Müziği Çal
remote.setCommand(play);
remote.pressButton(); // Müzik çalıyor...
// Geri Al (Müziği Durdur)
remote.pressUndo(); // Müzik durduruldu.
// Müziği Durdur
remote.setCommand(stop);
remote.pressButton(); // Müzik durduruldu.
// Geri Al (Müziği Çal)
remote.pressUndo(); // Müzik çalıyor...
}
}
Nasıl Çalışır?
İstemci (MusicPlayerDemo), PlayMusicCommand ve StopMusicCommand komutlarını kullanarak müzik çaları kontrol eder.
RemoteControl üzerinde bir butona basıldığında (pressButton), belirlenen komut (play veya stop) çalıştırılır ve son komut olarak saklanır.
pressUndo çağrıldığında, en son komutun undo metodu çalıştırılır, böylece son yapılan işlem geri alınır.
Bu örnek, Command deseninin geri alma (undo) işlevselliğini nasıl kolayca destekleyebileceğini gösterir. Bu, kullanıcı hatalarını düzeltmek veya esnek bir kullanıcı deneyimi sağlamak için uygulamalarda sıklıkla kullanılır.