Menu
Coddy logo textTech

Komut Kalıbı

Coddy'nin Java Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 70 / 87.

Komut Deseni (Command Pattern), bir isteği, istekle ilgili tüm bilgileri içeren bağımsız bir nesneye dönüştüren davranışsal bir tasarım desenidir. Bu dönüşüm; istekleri metot argümanları olarak iletmenize, bir isteğin yürütülmesini geciktirmenize veya sıraya koymanıza ve geri alınabilir işlemleri desteklemenize olanak tanır.

Bunu bir restoran gibi düşünün: aşçıya doğrudan ne pişireceğini söylemek yerine, siparişinizi bir fişe yazarsınız. Garson (invoker), fişi (command) mutfağa götürür; burada fiş sıraya alınabilir, önceliklendirilebilir veya hatta iptal edilebilir. Bu desen, işlemi çağıran nesne ile işlemi gerçekleştiren nesneyi birbirinden ayırır.

Kalıbın dört ana bileşeni vardır: execute metodunu bildiren bir Command arayüzü, belirli eylemleri gerçekleştiren ConcreteCommand sınıfları, asıl işi yapan bir Receiver ve komutları tetikleyen bir Invoker:

interface Command {
    void execute();
}
class Light {  // Alıcı
    public void turnOn() {
        System.out.println("Light is ON");
    }
    public void turnOff() {
        System.out.println("Light is OFF");
    }
}
class LightOnCommand implements Command {
    private Light light;
    
    public LightOnCommand(Light light) {
        this.light = light;
    }
    
    public void execute() {
        light.turnOn();
    }
}
class RemoteControl {  // Çağırıcı
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void pressButton() {
        command.execute();
    }
}

Çağırıcı hangi işlemin gerçekleştirileceğini bilmez—sadece execute() metodunu çağırır:

Light light = new Light();
Command lightOn = new LightOnCommand(light);

RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();  // Çıktı: Işık AÇIK

Komut Deseni (Command Pattern); işlemleri kuyruğa almanız, geri al/yinele işlevselliği uygulamanız veya görevleri daha sonra yürütülmek üzere zamanlamanız gerektiğinde mükemmel sonuçlar verir. Her komut, bir eylemi gerçekleştirmek için gereken her şeyi kapsüller; bu da sisteminizi daha esnek ve genişletilebilir hale getirir.

challenge icon

Görev

Kolay

Komut Desenini (Command Pattern) kullanarak akıllı bir ev otomasyon sistemi kuralım! Çeşitli ev cihazlarının komutlar aracılığıyla kontrol edilebildiği, eylemlerin sıraya alınabildiği, yürütülebildiği ve hatta daha sonra kullanılmak üzere saklanabildiği bir sistem oluşturacaksınız; tıpkı her cihazın dahili olarak nasıl çalıştığını bilmesine gerek duymayan evrensel bir uzaktan kumanda gibi.

Kodunuzu dört dosya halinde düzenleyeceksiniz:

  • Command.java: Tüm cihaz komutlarının uygulayacağı Command arayüzünü tanımlayın. Komutun eylemini gerçekleştiren tek bir execute() metodu bildirmelidir.
  • Devices.java: Akıllı ev cihazlarını temsil eden iki alıcı (receiver) sınıfı oluşturun:

    Television - TV is now ON yazdıran powerOn(), TV is now OFF yazdıran powerOff() ve TV channel set to [channel] yazdıran setChannel(int channel) metodlarına sahiptir.

    Thermostat - Thermostat set to [temp] degrees yazdıran setTemperature(int temp) ve Thermostat turned OFF yazdıran turnOff() metodlarına sahiptir.

  • Commands.java: Cihaz işlemlerini kapsülleyen somut komut sınıfları oluşturun:

    TVOnCommand - Yapıcısında (constructor) bir Television alır ve yürütüldüğünde powerOn() metodunu çağırır.

    TVOffCommand - Yapıcısında bir Television alır ve yürütüldüğünde powerOff() metodunu çağırır.

    TVChannelCommand - Yapıcısında bir Television ve bir int channel alır ve yürütüldüğünde bu kanalla setChannel() metodunu çağırır.

    ThermostatSetCommand - Yapıcısında bir Thermostat ve bir int temperature alır ve yürütüldüğünde bu değerle setTemperature() metodunu çağırır.

  • Main.java: Bir komutu saklamak için setCommand(Command cmd) metoduna ve saklanan komutu yürütmek için pressButton() metoduna sahip bir RemoteControl sınıfı (çağırıcı/invoker) oluşturun.

    Ana metodunuzda (main method) iki girdi alacaksınız: bir TV kanal numarası (tam sayı) ve bir termostat sıcaklığı (tam sayı).

    Bir Television ve bir Thermostat oluşturun. Bir RemoteControl oluşturun ve Komut Desenini şu şekilde gösterin:

    1. Bir TVOnCommand ayarlayın ve düğmeye basın
    2. Girdi kanalınızla bir TVChannelCommand ayarlayın ve düğmeye basın
    3. Girdi sıcaklığınızla bir ThermostatSetCommand ayarlayın ve düğmeye basın
    4. Bir TVOffCommand ayarlayın ve düğmeye basın

Sırasıyla iki girdi alacaksınız: TV kanalı (tam sayı) ve termostat sıcaklığı (tam sayı).

Örneğin, 5 ve 72 girdileriyle çıktınız şöyle olacaktır:

TV is now ON
TV channel set to 5
Thermostat set to 72 degrees
TV is now OFF

RemoteControl sınıfının cihazlarla asla doğrudan etkileşime girmediğine, yalnızca Command arayüzünü bildiğine dikkat edin. Her komut, eylemini gerçekleştirmek için gereken her şeyi kapsüller, bu da çağırıcıyı değiştirmeden yeni cihazlar ve komutlar eklemeyi kolaylaştırır!

Kopya kağıdı

Komut Deseni (Command Pattern), bir isteği nesne olarak kapsülleyen, istemcileri farklı isteklerle parametreleştirmenize, istekleri kuyruğa almanıza veya günlüğe kaydetmenize ve geri alınabilir işlemleri desteklemenize olanak tanıyan davranışsal bir tasarım desenidir.

Bu desen, işlemi başlatan nesneyi (invoker) işlemi gerçekleştiren nesneden (receiver) ayırır.

Temel Bileşenler

  • Command: execute() metodunu bildiren arayüz (interface)
  • ConcreteCommand: Belirli eylemleri uygulayan sınıflar
  • Receiver: Gerçek işi yapan nesne
  • Invoker: Komutları tetikleyen nesne

Temel Yapı

// Command arayüzü
interface Command {
    void execute();
}

// Receiver (Alıcı)
class Light {
    public void turnOn() {
        System.out.println("Light is ON");
    }
    public void turnOff() {
        System.out.println("Light is OFF");
    }
}

// ConcreteCommand (Somut Komut)
class LightOnCommand implements Command {
    private Light light;
    
    public LightOnCommand(Light light) {
        this.light = light;
    }
    
    public void execute() {
        light.turnOn();
    }
}

// Invoker (Başlatıcı)
class RemoteControl {
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void pressButton() {
        command.execute();
    }
}

Kullanım

Light light = new Light();
Command lightOn = new LightOnCommand(light);

RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();  // Çıktı: Light is ON

Başlatıcı (invoker) hangi eylemin gerçekleştirileceğini bilmez; sadece execute() metodunu çağırır. Bu, sistemi esnek ve genişletilebilir hale getirir; işlemleri kuyruğa almak, geri al/yinele (undo/redo) işlevselliğini uygulamak veya görevleri zamanlamak için idealdir.

Kendin dene

import java.util.Scanner;

// TODO: RemoteControl sınıfını (çağırıcı/invoker) şunlarla oluşturun:
// - bir komutu saklamak için setCommand(Command cmd) metodu
// - saklanan komutu çalıştırmak için pressButton() metodu

class RemoteControl {
    // TODO: RemoteControl sınıfını uygulayın
}

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Girdileri oku
        int channel = scanner.nextInt();
        int temperature = scanner.nextInt();
        
        // TODO: Bir Television ve bir Thermostat oluşturun
        
        // TODO: Bir RemoteControl oluşturun
        
        // TODO: Command Pattern'i gösterin:
        // 1. Bir TVOnCommand ayarlayın ve düğmeye basın
        // 2. Giriş kanalıyla bir TVChannelCommand ayarlayın ve düğmeye basın
        // 3. Giriş sıcaklığıyla bir ThermostatSetCommand ayarlayın ve düğmeye basın
        // 4. Bir TVOffCommand ayarlayın ve düğmeye basın
        
        scanner.close();
    }
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler