Menu
CoddyTech

Pola Command

Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan C++ di Coddy. Pelajaran 96 dari 104.

Command pattern mengemas permintaan sebagai object, sehingga kamu dapat mengatur parameter client dengan berbagai permintaan, mengantrekan operasi, atau mendukung fungsi undo. Pola ini memisahkan object yang memanggil operasi dari object yang tahu cara menjalankannya.

Pola ini memiliki empat komponen utama: antarmuka Command dengan method execute(), Concrete Commands yang menerapkan tindakan tertentu, Receiver yang melakukan pekerjaan sebenarnya, dan Invoker yang memicu perintah:

#include <iostream>
#include <memory>
#include <vector>

// Penerima: tahu cara menjalankan operasi
class Light {
public:
    void turnOn() { std::cout << "Light is ON\n"; }
    void turnOff() { std::cout << "Light is OFF\n"; }
};

// Antarmuka perintah
class Command {
public:
    virtual void execute() = 0;
    virtual void undo() = 0;
    virtual ~Command() = default;
};

// Perintah konkret
class LightOnCommand : public Command {
    Light& light;
public:
    LightOnCommand(Light& l) : light(l) {}
    void execute() override { light.turnOn(); }
    void undo() override { light.turnOff(); }
};

class LightOffCommand : public Command {
    Light& light;
public:
    LightOffCommand(Light& l) : light(l) {}
    void execute() override { light.turnOff(); }
    void undo() override { light.turnOn(); }
};

// Pemanggil
class RemoteControl {
    std::vector<std::unique_ptr<Command>> history;
public:
    void pressButton(std::unique_ptr<Command> cmd) {
        cmd->execute();
        history.push_back(std::move(cmd));
    }
    
    void pressUndo() {
        if (!history.empty()) {
            history.back()->undo();
            history.pop_back();
        }
    }
};

Setiap perintah menyimpan referensi ke penerimanya dan memanggil method yang sesuai saat dijalankan. Pemanggil tidak tahu tindakan apa yang akan terjadi, ia hanya memanggil execute(). Dengan menyimpan perintah dalam riwayat, kamu dapat dengan mudah menerapkan undo dengan memanggil method undo() pada setiap perintah.

Gunakan Command saat kamu perlu mengantrekan operasi, menerapkan undo/redo, atau memisahkan pengirim permintaan dari penangan permintaan.

challenge icon

Tantangan

Mudah

Mari buat Editor Teks dengan fitur pembatalan menggunakan pola Command. Kamu akan membuat sistem yang membungkus operasi penyuntingan, seperti menyisipkan dan menghapus teks, sebagai object perintah. Dengan begitu, pengguna dapat menjalankan tindakan lalu membatalkannya dalam urutan terbalik, seperti di editor teks sungguhan.

Kamu akan menyusun kodemu dalam empat file:

  • TextDocument.h: Buat class penerima yang menyimpan dan mengolah isi teks sebenarnya.

    Class TextDocument harus menyimpan isi dokumen sebagai string. Implementasikan method berikut:

    • insertText(const std::string& text): menambahkan teks di akhir isi
    • deleteText(int count): menghapus count karakter terakhir dari isi, tidak melakukan apa pun jika count melebihi panjang isi
    • getContent(): mengembalikan isi saat ini sebagai referensi const
  • Command.h: Definisikan antarmuka perintah dan class perintah konkret.

    Buat class abstrak Command dengan method virtual murni execute() dan undo(), serta destruktor virtual.

    Lalu implementasikan dua perintah konkret:

    • InsertCommand: menerima referensi ke TextDocument dan string yang akan disisipkan. Saat dijalankan, perintah ini menyisipkan teks. Saat dibatalkan, perintah ini menghapus jumlah karakter yang sama dengan jumlah karakter yang disisipkan.
    • DeleteCommand: menerima referensi ke TextDocument dan jumlah karakter yang akan dihapus. Perintah ini perlu menyimpan teks yang dihapus agar dapat memulihkannya saat dibatalkan. Saat dijalankan, perintah ini menghapus karakter dari akhir. Saat dibatalkan, perintah ini menyisipkan kembali teks yang disimpan.
  • TextEditor.h: Buat pemanggil yang mengelola pelaksanaan perintah dan riwayatnya.

    Class TextEditor harus menyimpan referensi ke TextDocument dan memelihara riwayat perintah yang telah dijalankan menggunakan vector berisi unique_ptr<Command>. Implementasikan:

    • executeCommand(std::unique_ptr<Command> cmd): menjalankan perintah dan menambahkannya ke riwayat
    • undo(): membatalkan perintah terbaru dan menghapusnya dari riwayat, tidak melakukan apa pun jika riwayat kosong
    • showContent(): menampilkan isi dokumen saat ini, atau [empty] jika isinya kosong
  • main.cpp: Tunjukkan pola Command dengan fitur pembatalan.

    Baca tiga input:

    1. Teks pertama yang akan disisipkan (string)
    2. Teks kedua yang akan disisipkan (string)
    3. Jumlah karakter yang akan dihapus (bilangan bulat)

    Buat TextDocument dan TextEditor. Lalu lakukan operasi berikut secara berurutan dan tampilkan isi setelah setiap langkah:

    1. Sisipkan teks pertama, lalu tampilkan isi
    2. Sisipkan teks kedua, lalu tampilkan isi
    3. Hapus jumlah karakter yang ditentukan, lalu tampilkan isi
    4. Batalkan sekali, lalu tampilkan isi
    5. Batalkan sekali lagi, lalu tampilkan isi

Misalnya, dengan input Hello, World, dan 3:

Hello
Hello World
Hello Wo
Hello World
Hello

Dengan input Code, Editor, dan 6:

Code
CodeEditor
Code
CodeEditor
Code

Perhatikan bagaimana setiap perintah tahu cara membatalkan tindakannya sendiri. DeleteCommand mengingat apa yang dihapus agar dapat memulihkannya, sedangkan InsertCommand tahu persis berapa banyak karakter yang harus dihapus saat pembatalan. Inilah keunggulan pola Command: operasi menjadi object mandiri yang dapat disimpan, dijalankan, dan dibatalkan.

Coba sendiri

#include <iostream>
#include <string>
#include <memory>
#include "TextDocument.h"
#include "Command.h"
#include "TextEditor.h"

int main() {
    // Baca input
    std::string firstText;
    std::string secondText;
    int deleteCount;
    
    std::getline(std::cin, firstText);
    std::getline(std::cin, secondText);
    std::cin >> deleteCount;

    // TODO: Buat TextDocument dan TextEditor
    
    // TODO: Lakukan operasi secara berurutan, lalu tampilkan konten setelah setiap operasi:
    // 1. Sisipkan teks pertama, lalu tampilkan konten
    // 2. Sisipkan teks kedua, lalu tampilkan konten
    // 3. Hapus sejumlah karakter yang ditentukan, lalu tampilkan konten
    // 4. Batalkan sekali, lalu tampilkan konten
    // 5. Batalkan sekali lagi, lalu tampilkan konten
    
    // Petunjuk: Gunakan std::make_unique<InsertCommand>(...) dan 
    //       std::make_unique<DeleteCommand>(...) untuk membuat perintah

    return 0;
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Object

Latihan sendiri: Compiler C++ online