Menu
CoddyTech

Pola Command

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

Pola Command membungkus permintaan sebagai object, sehingga kamu dapat mengatur client dengan berbagai permintaan, mengantrekan operasi, atau mendukung fungsi pembatalan. Pola ini memisahkan object yang memanggil operasi dari object yang mengetahui cara menjalankannya.

Pola ini memiliki empat komponen utama: antarmuka Perintah dengan metode execute(), Perintah Konkret yang menerapkan tindakan tertentu, Penerima yang melakukan pekerjaan sebenarnya, dan Pemanggil 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 pembatalan dengan memanggil method undo() setiap perintah.

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

challenge icon

Tantangan

Mudah

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

Kamu akan menyusun kodemu dalam empat file:

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

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

    • insertText(const std::string& text): menambahkan teks di akhir konten
    • deleteText(int count): menghapus count karakter terakhir dari konten. Jangan lakukan apa pun jika count melebihi panjang konten.
    • getContent(): mengembalikan konten 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 yang disisipkan.
    • DeleteCommand: menerima referensi ke TextDocument dan jumlah karakter yang akan dihapus. Perintah ini harus 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 riwayat.

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

    • executeCommand(std::unique_ptr<Command> cmd): menjalankan perintah dan menambahkannya ke riwayat
    • undo(): membatalkan perintah terbaru dan menghapusnya dari riwayat. Jangan lakukan apa pun jika riwayat kosong.
    • showContent(): menampilkan konten dokumen saat ini, atau [empty] jika kontennya kosong
  • main.cpp: Tunjukkan pola Command dengan fungsi 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 konten setelah setiap langkah:

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

Contohnya, 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 bahwa setiap perintah mengetahui cara membatalkan tindakannya sendiri. DeleteCommand mengingat teks yang dihapusnya agar dapat memulihkannya, dan InsertCommand mengetahui persis jumlah karakter yang harus dihapus saat dibatalkan. Inilah kekuatan 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 karakter sebanyak jumlah 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