Menu
Coddy logo textTech

Komut Kalıbı

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

Komut deseni (Command pattern), bir isteği bir nesne olarak kapsüller; bu da istemcileri farklı isteklerle parametreleştirmenize, işlemleri kuyruğa almanıza veya geri alma (undo) işlevini desteklemenize olanak tanır. Bir metodu doğrudan çağırmak yerine, eylemi saklanabilen, aktarılabilen veya daha sonra yürütülebilen bir komut nesnesi içine sararsınız.

Desen üç temel bileşenden oluşur: bir execute metoduna sahip bir Command arayüzü, belirli eylemleri uygulayan Concrete Commands ve asıl işi gerçekleştiren bir Receiver. İsteğe bağlı bir Invoker, komutların ne yaptığını bilmeden onları tetikler:

abstract class Command {
  void execute();
}

class Light {
  void turnOn() => print('Light is ON');
  void turnOff() => print('Light is OFF');
}

class TurnOnCommand implements Command {
  final Light light;
  TurnOnCommand(this.light);

  @override
  void execute() => light.turnOn();
}

class TurnOffCommand implements Command {
  final Light light;
  TurnOffCommand(this.light);

  @override
  void execute() => light.turnOff();
}

class RemoteControl {
  Command? _command;

  void setCommand(Command command) {
    _command = command;
  }

  void pressButton() {
    _command?.execute();
  }
}

void main() {
  var light = Light();
  var remote = RemoteControl();

  remote.setCommand(TurnOnCommand(light));
  remote.pressButton();  // Işık AÇIK

  remote.setCommand(TurnOffCommand(light));
  remote.pressButton();  // Işık KAPALI
}

RemoteControl ışıklar hakkında hiçbir şey bilmez; sadece kendisine verilen komutu yürütür. Bu ayrıştırma (decoupling), çağırıcıyı (invoker) değiştirmeden yeni komutlar eklemeyi kolaylaştırır. Komut (Command) deseni; eylemleri birinci sınıf nesneler olarak ele almanız gereken geri al/yinele (undo/redo) sistemleri, görev kuyrukları veya makro kaydı uygulamak için idealdir.

challenge icon

Görev

Kolay

Komut (Command) desenini kullanarak bir metin düzenleyici komut sistemi oluşturalım! Metin işlemlerini komut nesneleri olarak kapsülleyen bir sistem oluşturacaksınız; bu sistem, bir düzenleyicinin her bir işlemin ayrıntılarını bilmeden farklı eylemleri yürütmesine olanak tanır. Bu, Komut deseninin klasik bir kullanım örneğidir - her eylemin bir nesne olarak saklandığı bir geri al/yinele (undo/redo) sistemi gibi düşünün.

Kodunuzu iki dosyada organize edeceksiniz:

  • commands.dart: Komut sisteminizi burada oluşturun. Bir execute() metodu bildiren soyut bir Command sınıfı ile başlayın. Ardından, bir String content alanı (başlangıçta boş) tutan ve üç metoda sahip olan bir TextDocument sınıfı (alıcı/receiver) oluşturun:
    • append(String text) - içeriğin sonuna metin ekler
    • clear() - içeriği boş bir dizeye ayarlar
    • show() - Document: [content] yazdırır
    Şimdi bir TextDocument ile çalışan üç somut komut uygulayın:
    • AppendCommand - yapıcı metodunda (constructor) bir belge ve metin alır ve yürütüldüğünde metni ekler
    • ClearCommand - yapıcı metodunda bir belge alır ve yürütüldüğünde belgeyi temizler
    • ShowCommand - yapıcı metodunda bir belge alır ve yürütüldüğünde içeriğini gösterir
    Son olarak, bir komut listesi saklayan bir TextEditor sınıfı (çağırıcı/invoker) oluşturun. Komutları sıraya koymak için bir addCommand(Command command) metoduna ve sıradaki tüm komutları sırayla yürüten bir runAll() metoduna sahip olmalıdır.
  • main.dart: Komutlar dosyanızı içe aktarın ve Komut desenini gösterin. Bir TextDocument ve bir TextEditor oluşturun. Şu komutları sırasıyla kuyruğa ekleyin: Hello ekle, World ekle, belgeyi göster, ! ekle, tekrar göster, belgeyi temizle ve son bir kez daha göster. Ardından kuyruktaki tüm komutları çalıştırın.

TextEditor sınıfının ekleme, temizleme veya gösterme hakkında hiçbir şey bilmediğine dikkat edin - sadece kendisine verilen komutları yürütür. Bu ayrıştırma (decoupling), Komut deseninin özüdür!

Beklenen çıktı:

Document: Hello World
Document: Hello World!
Document: 

Kopya kağıdı

Command deseni (Command pattern), bir isteği bir nesne olarak kapsülleyerek istemcileri farklı isteklerle parametreleştirmenize, işlemleri kuyruğa almanıza veya geri alma (undo) işlevini desteklemenize olanak tanır.

Desen üç temel bileşenden oluşur:

  • Bir execute metoduna sahip Command arayüzü
  • Belirli eylemleri uygulayan Concrete Commands (Somut Komutlar)
  • Asıl işi gerçekleştiren Receiver (Alıcı)
  • Ne yaptıklarını bilmeden komutları tetikleyen Invoker (isteğe bağlı)

Temel yapı:

abstract class Command {
  void execute();
}

class Receiver {
  void action() => print('Action performed');
}

class ConcreteCommand implements Command {
  final Receiver receiver;
  ConcreteCommand(this.receiver);

  @override
  void execute() => receiver.action();
}

class Invoker {
  Command? _command;

  void setCommand(Command command) {
    _command = command;
  }

  void trigger() {
    _command?.execute();
  }
}

Bir ışık kontrol sistemi ile örnek:

class Light {
  void turnOn() => print('Light is ON');
  void turnOff() => print('Light is OFF');
}

class TurnOnCommand implements Command {
  final Light light;
  TurnOnCommand(this.light);

  @override
  void execute() => light.turnOn();
}

class RemoteControl {
  Command? _command;

  void setCommand(Command command) {
    _command = command;
  }

  void pressButton() {
    _command?.execute();
  }
}

void main() {
  var light = Light();
  var remote = RemoteControl();

  remote.setCommand(TurnOnCommand(light));
  remote.pressButton();  // Light is ON
}

Invoker, receiver hakkında hiçbir şey bilmez; sadece kendisine verilen komutu yürütür. Bu ayrıştırma (decoupling), invoker'ı değiştirmeden yeni komutlar eklemeyi kolaylaştırır.

Kendin dene

import 'commands.dart';

void main() {
  // TODO: Bir TextDocument örneği oluşturun

  // TODO: Bir TextEditor örneği oluşturun

  // TODO: Aşağıdaki komutları sırasıyla kuyruğa ekleyin:
  // 1. "Hello" ekle
  // 2. " World" ekle
  // 3. Belgeyi göster
  // 4. "!" ekle
  // 5. Belgeyi tekrar göster
  // 6. Belgeyi temizle
  // 7. Belgeyi son bir kez göster

  // TODO: Kuyruğa alınan tüm komutları çalıştırın
}
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