Command Pattern là một mẫu thiết kế phần mềm cho phép bạn biến các yêu cầu (commands) thành các đối tượng, từ đó tách biệt việc thực hiện yêu cầu và việc gọi yêu cầu. Mẫu này rất hữu ích trong việc lưu trữ các hành động, thực hiện undo/redo, và thực hiện các tác vụ không đồng bộ.

Dưới đây là cách triển khai Command Pattern trong JavaScript với một ví dụ minh họa.

Bước 1: Định nghĩa Command Interface

Trước tiên, chúng ta sẽ định nghĩa một interface cho các command. Trong JavaScript, bạn có thể sử dụng các lớp (classes) hoặc các hàm (functions) để tạo ra các command cụ thể.

Bước 2: Tạo các Command cụ thể

Chúng ta sẽ tạo ra một số command cụ thể để thực hiện các hành động như “turn on light” và “turn off light”.

Bước 3: Tạo Invoker

Invoker sẽ là đối tượng thực hiện việc gọi command.

Bước 4: Sử dụng Command Pattern

Dưới đây là triển khai hoàn chỉnh:

// Command Interface
class Command {
    execute() {}
    undo() {}
}

// Command cụ thể: TurnOnLightCommand
class TurnOnLightCommand extends Command {
    constructor(light) {
        super();
        this.light = light;
    }

    execute() {
        this.light.turnOn();
    }

    undo() {
        this.light.turnOff();
    }
}

// Command cụ thể: TurnOffLightCommand
class TurnOffLightCommand extends Command {
    constructor(light) {
        super();
        this.light = light;
    }

    execute() {
        this.light.turnOff();
    }

    undo() {
        this.light.turnOn();
    }
}

// Receiver: Light
class Light {
    turnOn() {
        console.log("Light is ON");
    }

    turnOff() {
        console.log("Light is OFF");
    }
}

// Invoker: RemoteControl
class RemoteControl {
    constructor() {
        this.commandHistory = [];
    }

    executeCommand(command) {
        command.execute();
        this.commandHistory.push(command);
    }

    undoCommand() {
        const command = this.commandHistory.pop();
        if (command) {
            command.undo();
        }
    }
}

// Sử dụng Command Pattern
const light = new Light();
const turnOnCommand = new TurnOnLightCommand(light);
const turnOffCommand = new TurnOffLightCommand(light);
const remoteControl = new RemoteControl();

// Bật đèn
remoteControl.executeCommand(turnOnCommand);  // In ra "Light is ON"

// Tắt đèn
remoteControl.executeCommand(turnOffCommand);  // In ra "Light is OFF"

// Thực hiện undo
remoteControl.undoCommand();  // In ra "Light is ON"
remoteControl.undoCommand();  // In ra "Light is OFF"

Giải thích mã

  1. Command Interface: Tạo một lớp Command với các phương thức executeundo. Đây là lớp cha cho tất cả các command cụ thể.
  2. Command Cụ thể: Tạo các lớp như TurnOnLightCommandTurnOffLightCommand, kế thừa từ lớp Command. Các lớp này thực hiện hành động bật hoặc tắt đèn.
  3. Receiver: Lớp Light chứa logic để bật và tắt đèn.
  4. Invoker: Lớp RemoteControl lưu trữ lịch sử của các command đã thực hiện và cung cấp phương thức để thực hiện hoặc undo các command.
  5. Sử dụng Command Pattern: Tạo một đối tượng Light, tạo các command cụ thể cho việc bật và tắt đèn, và sử dụng RemoteControl để thực hiện chúng.

Kết luận

Command Pattern cung cấp một cách tiếp cận mạnh mẽ để tách biệt các hành động và xử lý chúng một cách linh hoạt. Triển khai mẫu này trong JavaScript giúp cho mã nguồn trở nên rõ ràng, dễ bảo trì và có thể mở rộng. Bạn có thể dễ dàng thêm các command mới mà không cần thay đổi mã nguồn đã có. Nếu bạn có thêm câu hỏi hoặc cần làm rõ điều gì, hãy cho tôi biết!