Command Pattern là một mẫu thiết kế thuộc nhóm Behavioral Patterns (mẫu hành vi), giúp tách biệt đối tượng phát ra lệnh (gọi là invoker) và đối tượng thực thi lệnh (receiver) bằng cách đóng gói yêu cầu vào một đối tượng dưới dạng command. Mỗi lệnh (command) đại diện cho một hành động hoặc yêu cầu cụ thể, bao gồm thông tin về đối tượng nào cần thực thi hành động đó.
Command Pattern cho phép đóng gói các yêu cầu dưới dạng các đối tượng command, giúp dễ dàng thực hiện các hành động như undo (hoàn tác), redo (làm lại), logging (ghi log), hoặc queue (xếp hàng đợi các lệnh). Bằng cách tách biệt logic xử lý lệnh và logic gọi lệnh, pattern này tạo ra sự linh hoạt trong việc xử lý và tổ chức các lệnh.
Giả sử bạn đang thiết kế một ứng dụng đồ họa với nhiều thao tác khác nhau như vẽ hình, xóa hình, thay đổi màu sắc,… Các thao tác này có thể được thực hiện theo nhiều cách khác nhau và có thể cần chức năng undo/redo. Nếu không sử dụng Command Pattern, bạn sẽ phải xử lý từng thao tác này một cách trực tiếp, điều này có thể khiến mã nguồn trở nên phức tạp và khó bảo trì.
Command Pattern cho phép đóng gói từng thao tác vào các đối tượng riêng lẻ, giúp việc thêm chức năng undo/redo, tổ chức các lệnh theo hàng đợi, hoặc ghi lại các hành động trở nên dễ dàng hơn mà không làm phức tạp mã nguồn chính.
Command Pattern bao gồm các thành phần chính:
execute()
của một đối tượng Command.execute()
để thực hiện hành động.Giả sử chúng ta thiết kế một hệ thống điều khiển từ xa với nhiều nút để bật và tắt các thiết bị điện như đèn, quạt, v.v.
// Interface Command định nghĩa phương thức execute() public interface Command { void execute(); } // Lớp cụ thể triển khai Command cho việc bật đèn public class LightOnCommand implements Command { private Light light; public LightOnCommand(Light light) { this.light = light; } @Override public void execute() { light.on(); // Gọi phương thức on() của đối tượng Light } } // Lớp cụ thể triển khai Command cho việc tắt đèn public class LightOffCommand implements Command { private Light light; public LightOffCommand(Light light) { this.light = light; } @Override public void execute() { light.off(); // Gọi phương thức off() của đối tượng Light } } // Lớp Receiver là đối tượng thực hiện hành động thực sự public class Light { public void on() { System.out.println("Light is ON"); } public void off() { System.out.println("Light is OFF"); } } // Lớp Invoker giữ các Command và gọi execute() để thực hiện lệnh public class RemoteControl { private Command command; public void setCommand(Command command) { this.command = command; } public void pressButton() { command.execute(); // Gọi phương thức execute() của Command } } // Sử dụng Command Pattern public class Main { public static void main(String[] args) { Light livingRoomLight = new Light(); // Receiver // Tạo các lệnh cụ thể Command lightOn = new LightOnCommand(livingRoomLight); Command lightOff = new LightOffCommand(livingRoomLight); RemoteControl remote = new RemoteControl(); // Invoker // Bật đèn remote.setCommand(lightOn); remote.pressButton(); // Output: Light is ON // Tắt đèn remote.setCommand(lightOff); remote.pressButton(); // Output: Light is OFF } }
execute()
.execute()
để thực hiện lệnh.main()
, chúng ta tạo ra các lệnh bật/tắt đèn và cấu hình chúng cho điều khiển từ xa. Khi nhấn nút trên điều khiển, lệnh sẽ được thực hiện.Command Pattern dễ dàng hỗ trợ tính năng undo/redo nhờ việc lưu lại trạng thái trước và sau khi thực hiện lệnh.
// Interface Command với thêm phương thức undo() public interface Command { void execute(); void undo(); } // Lớp cụ thể triển khai Command cho việc bật đèn public class LightOnCommand implements Command { private Light light; public LightOnCommand(Light light) { this.light = light; } @Override public void execute() { light.on(); } @Override public void undo() { light.off(); // Đảo ngược hành động } } // Lớp cụ thể triển khai Command cho việc tắt đèn public class LightOffCommand implements Command { private Light light; public LightOffCommand(Light light) { this.light = light; } @Override public void execute() { light.off(); } @Override public void undo() { light.on(); // Đảo ngược hành động } }
Với các phương thức undo()
này, bạn có thể dễ dàng gọi lại hành động trước đó để hoàn tác thao tác đã thực hiện.
Command Pattern là một mẫu thiết kế mạnh mẽ cho phép đóng gói các yêu cầu thành các đối tượng độc lập, dễ dàng quản lý và mở rộng. Nó giúp giảm sự phụ thuộc giữa các thành phần của hệ thống, hỗ trợ undo/redo và có khả năng lưu trữ, xếp hàng các lệnh. Điều này làm cho Command Pattern trở nên lý tưởng trong các hệ thống yêu cầu tính linh hoạt và khả năng mở rộng cao.