Mẫu lệnh
Thuộc phần Lập trình hướng đối tượng trong hành trình PHP của Coddy. Bài học 75 trên 91.
Command Pattern là một mẫu thiết kế hành vi, biến một yêu cầu thành một đối tượng độc lập chứa mọi thông tin về yêu cầu đó. Cách chuyển đổi này cho phép bạn truyền yêu cầu làm đối số cho phương thức, trì hoãn hoặc đưa yêu cầu vào hàng đợi để thực thi, đồng thời hỗ trợ các thao tác có thể hoàn tác.
Hãy nghĩ đến một nhà hàng.
Khi bạn gọi món, nhân viên phục vụ ghi món bạn gọi vào phiếu (lệnh), mang phiếu vào bếp và đầu bếp thực hiện món đó. Nhân viên phục vụ không cần biết cách nấu ăn, họ chỉ cần chuyển lệnh.
Điều này tách bên yêu cầu khỏi bên thực thi.
Đây là cách triển khai cơ bản:
<?php
interface Command {
public function execute(): string;
}class Light {
public function on(): string { return "Light is ON"; }
public function off(): string { return "Light is OFF"; }
}class LightOnCommand implements Command {
public function __construct(private Light $light) {}
public function execute(): string {
return $this->light->on();
}
}class LightOffCommand implements Command {
public function __construct(private Light $light) {}
public function execute(): string {
return $this->light->off();
}
}
Bộ gọi kích hoạt các lệnh mà không cần biết chúng làm gì:
<?php
class RemoteControl {
public function press(Command $command): string {
return $command->execute();
}
}$light = new Light();
$remote = new RemoteControl();
echo $remote->press(new LightOnCommand($light)) . "\n";
echo $remote->press(new LightOffCommand($light));
Đầu ra:
Light is ON
Light is OFFMẫu lệnh phát huy hiệu quả khi bạn cần xếp hàng đợi các thao tác, triển khai chức năng hoàn tác hoặc ghi nhật ký hành động. Mỗi lệnh đều độc lập, giúp bạn dễ dàng thêm lệnh mới mà không cần sửa đổi code hiện có.
Thử thách
DễHãy xây dựng một hệ thống lệnh cho trình soạn thảo văn bản bằng Command Pattern. Trình soạn thảo văn bản thường cần hỗ trợ các thao tác như viết văn bản, xóa văn bản và hoàn tác thao tác. Mỗi thao tác trở thành một đối tượng lệnh độc lập có thể được thực thi thông qua một giao diện thống nhất.
Bạn sẽ sắp xếp code trong bốn tệp:
Command.php: Định nghĩa giao diệnCommandvới một phương thức duy nhất làexecute(): string. Giao diện này xác định những gì mọi lệnh của trình soạn thảo phải tuân theo.TextEditor.php: Tạo lớpTextEditorđại diện cho đối tượng nhận, tức đối tượng thực hiện công việc. Trình soạn thảo của bạn cần:- Lưu nội dung văn bản hiện tại (bắt đầu bằng một chuỗi rỗng)
- Có phương thức
write(string $text): stringđể nối văn bản vào nội dung và trả về"Written: [text]" - Có phương thức
clear(): stringđể xóa nội dung và trả về"Content cleared" - Có phương thức
getContent(): stringđể trả về nội dung hiện tại
Commands.php: Bao gồm các tệp Command và TextEditor. Tạo hai lớp lệnh triển khai giao diệnCommand:WriteCommand: Nhận mộtTextEditorvà một chuỗi văn bản trong hàm khởi tạo. Phương thứcexecute()gọi phương thứcwrite()của trình soạn thảo và trả về kết quả.ClearCommand: Nhận mộtTextEditortrong hàm khởi tạo. Phương thứcexecute()gọi phương thứcclear()của trình soạn thảo và trả về kết quả.
main.php: Bao gồm tệp Commands. Bạn sẽ nhận hai đầu vào: loại lệnh ("write"hoặc"clear") và một chuỗi văn bản (chỉ dùng cho lệnh write).Tạo một đối tượng
TextEditor. Dựa vào loại lệnh, tạo đối tượng lệnh phù hợp. Sau đó, tạo một hàm gọi hoặc cơ chế đơn giản để gọiexecute()trên lệnh và in ra kết quả.Trên dòng mới, in nội dung hiện tại của trình soạn thảo theo định dạng này:
Content: [content](nếu nội dung rỗng, chỉ inContent:, không có gì sau dấu cách).
Thử thách này minh họa cách Command Pattern đóng gói từng thao tác thành một đối tượng. Đối tượng gọi lệnh không cần biết nó đang thực thi lệnh write hay clear. Nó chỉ cần gọi execute() và để lệnh xử lý các chi tiết.
Tự làm thử
<?php
require_once 'Commands.php';
// Đọc đầu vào
$commandType = trim(fgets(STDIN)); // "write" hoặc "clear"
$text = trim(fgets(STDIN)); // văn bản cho lệnh write
// TODO: Tạo một instance của TextEditor
// TODO: Dựa vào loại lệnh, tạo đối tượng lệnh phù hợp
// - Nếu là "write", tạo WriteCommand với trình soạn thảo và văn bản
// - Nếu là "clear", tạo ClearCommand với trình soạn thảo
// TODO: Tạo cơ chế gọi execute() trên đối tượng lệnh
// và in ra kết quả
// TODO: In nội dung hiện tại của trình soạn thảo theo định dạng: "Content: [content]"
// (nếu trống, chỉ in "Content: " và không in gì sau dấu cách)
?>Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về OOP
Tệp bên ngoàiGiới thiệu về OOPLớp và đối tượngTừ khóa $thisPhương thứcThuộc tínhHàm khởi tạo (__construct)Hàm hủy (__destruct)Ôn tập: máy tính đơn giản4Kế thừa
Kế thừa cơ bảnTừ khóa parent::Ghi đè phương thứcTừ khóa finalLớp trừu tượngÔn tập: hệ thống phân cấp nhân viên7Đóng gói
Công khai, được bảo vệ, riêng tưTìm hiểu sâu về bộ điều chỉnh quyền truy cậpGetter và setterẨn thông tinRút gọn hàm khởi tạo (8.0)Ôn tập: hệ thống hồ sơ học sinh10Các khái niệm OOP nâng cao
Kết hợp hay kế thừaTiêm phụ thuộcLớp ẩn danhKiểu liệt kê (PHP 8.1)Fiber (PHP 8.1)Tìm hiểu sâu về sao chép đối tượngBộ sinh và bộ lặp13Mẫu thiết kế phần 2
Mẫu lệnhMẫu bộ chuyển đổiMẫu trang tríMẫu phương thức khuôn mẫuMẫu trạng tháiMẫu tổ hợpMẫu Repository2Không gian tên và tự động nạp
Giới thiệu về không gian tênTừ khóa useChuẩn tự động nạp PSR-4Trình tự động nạp của ComposerÔn tập: dự án có tổ chức5Giao diện và hợp đồng
Giới thiệu về giao diệnTriển khai giao diệnTriển khai nhiều giao diệnGiao diện và lớp trừu tượngGợi ý kiểu với giao diệnÔn tập: Máy tính hình học8Phương thức ma thuật
Giới thiệu về phương thức ma thuật__toString và __debugInfo__get, __set, __isset, __unset__call và __callStatic__clone và sao chép đối tượng__serialize và __unserializeÔn tập: Bộ sưu tập tùy chỉnh3Thuộc tính của lớp
Thuộc tính instance và staticHằng số trong lớpPhương thức và thuộc tính staticThuộc tính private và protectedThuộc tính chỉ đọc (PHP 8.1)Ôn tập: Trình quản lý tài khoản ngân hàng6Đa hình
Xem lại việc ghi đè phương thứcĐa hình qua giao diệnGợi ý kiểu và kiểu hợpLiên kết tĩnh muộnÔn tập: bộ xử lý thanh toánTự luyện tập: Trình biên dịch PHP online