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.
Görev
KolayKomut (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. Birexecute()metodu bildiren soyut birCommandsınıfı ile başlayın. Ardından, birString contentalanı (başlangıçta boş) tutan ve üç metoda sahip olan birTextDocumentsınıfı (alıcı/receiver) oluşturun:append(String text)- içeriğin sonuna metin eklerclear()- içeriği boş bir dizeye ayarlarshow()-Document: [content]yazdırır
TextDocumentile çalışan üç somut komut uygulayın:AppendCommand- yapıcı metodunda (constructor) bir belge ve metin alır ve yürütüldüğünde metni eklerClearCommand- yapıcı metodunda bir belge alır ve yürütüldüğünde belgeyi temizlerShowCommand- yapıcı metodunda bir belge alır ve yürütüldüğünde içeriğini gösterir
TextEditorsınıfı (çağırıcı/invoker) oluşturun. Komutları sıraya koymak için biraddCommand(Command command)metoduna ve sıradaki tüm komutları sırayla yürüten birrunAll()metoduna sahip olmalıdır.main.dart: Komutlar dosyanızı içe aktarın ve Komut desenini gösterin. BirTextDocumentve birTextEditoroluşturun. Şu komutları sırasıyla kuyruğa ekleyin:Helloekle,Worldekle, 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
}
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
1OOP Temelleri
Harici DosyalarKütüphaneler ve ImportlarOOP'ye GirişSınıflar ve Nesnelerthis Anahtar KelimesiMetotlarÖrnek DeğişkenleriConstructor TemelleriÖzet - Basit Hesap Makinesi4Null Safety
Null Safety'ye GirişNullable ve Non-Nullable? ve ! OperatörleriLate Anahtar Kelimesi ve Null SafetyNull-Aware OperatörleriSınıflarda Null SafetyÖzet - Kullanıcı Profili Sistemi7Soyut Sınıflar ve Arayüzler
Soyut SınıflarSoyut MetotlarDart'ta ArayüzlerÖrtük ArayüzlerUygulama vs. GenişletmeÇoklu ArayüzlerÖzet - Şekil Hesaplayıcı10Koleksiyonlar ve Generic'ler
List, Set, Map Genel BakışTip Güvenli KoleksiyonlarGeneric SınıflarGeneric MetotlarGeneric KısıtlamalarIterable ve IteratorÖzet - Generic Depolama2Dart'ta Yapıcılar
Varsayılan Yapıcıİsimlendirilmiş Yapıcılarİlklendirme ListeleriSabit YapıcılarFabrika YapıcılarıYönlendiren YapıcılarÖzet - Şekil Oluşturucu5Kapsülleme
Public ve Private Üyeler_ Öneki KuralıKütüphane Düzeyinde GizlilikGetter ve Setter DetaylarıBilgi GizlemeÖzet - Öğrenci Kayıtları8Mixin'ler
Mixin'lere GirişMixin OluşturmaBirden Fazla Mixin KullanımıMixin'lerde on Anahtar KelimesiMixin vs KalıtımMixin vs ArayüzÖzet - Hayvan Sistemi11Özel Metotlar
toString() OverridehashCode ve == OverrideComparable Arayüzücall() MetodunoSuchMethod OverrideÖzet - Özel Koleksiyon14Tasarım Kalıpları Bölüm 1
Tasarım Kalıplarına GirişSingleton KalıbıFactory KalıbıObserver KalıbıStrategy Kalıbı17Final Meydan Okumaları
E-Öğrenme PlatformuBankacılık SistemiOyun Karakter SistemiAraç Kiralama Servisi3Sınıf Özellikleri
Instance ve Statik ÜyelerFinal ve Const AlanlarLate DeğişkenlerStatik Metotlar ve AlanlarGetters ve SettersÖzet - Banka Hesabı Yöneticisi6Kalıtım
Temel Kalıtımsuper Anahtar KelimesiMetot Ezme@override Anotasyonufinal Sınıf Anahtar KelimesiYapıcı Metotlar ve KalıtımÖzet - Çalışan Hiyerarşisi9Çok Biçimlilik
Çok Biçimlilik TemelleriInterface'ler ile Çok BiçimlilikÇalışma Zamanı Tip Kontrolüis ve as OperatörleriCovariant Anahtar KelimesiÖzet - Ödeme İşlemcisi12Asenkron OOP
Futures ve async/awaitStream TemelleriStream Controller'larAsenkron KurucularSınıf Metotlarında Asenkron KullanımıÖzet - Data Fetcher15Tasarım Kalıpları Bölüm 2
Komut KalıbıAdaptör KalıbıDekoratör KalıbıŞablon Metot KalıbıDurum KalıbıKompozit KalıbıRepository Kalıbı