Nội dung
Command là mẫu thiết kế hành vi chuyển đổi các yêu cầu hoặc hoạt động đơn giản thành các đối tượng. Việc chuyển đổi cho phép thực hiện lệnh hoãn lại hoặc từ xa, lưu trữ lịch sử lệnh, v.v.
Cách sử dụng mẫu
Sử dụng: Mẫu Command khá phổ biến trong mã C++. Thông thường, nó được sử dụng như một sự thay thế cho các lệnh gọi lại để tham số hóa các phần tử UI bằng các hành động. Nó cũng được sử dụng cho các tác vụ xếp hàng, theo dõi lịch sử hoạt động, v.v.
Nhận dạng: Mẫu Command có thể nhận biết được bằng các phương thức hành vi trong kiểu trừu tượng / giao diện (sender), phương thức này gọi một phương thức trong việc triển khai một kiểu giao diện / trừu tượng khác (receiver) đã được đóng gói bởi việc thực thi lệnh trong quá trình tạo nó. Các lớp Command thường được giới hạn trong các hành động cụ thể.
Chương trình mẫu
main.cpp
/**
* Giao diện Command khai báo một phương thức để thực hiện một lệnh.
*/
class Command {
public:
virtual ~Command() {
}
virtual void Execute() const = 0;
};
/**
* Một số Command có thể tự thực hiện các thao tác đơn giản.
*/
class SimpleCommand : public Command {
private:
std::string pay_load_;
public:
explicit SimpleCommand(std::string pay_load) : pay_load_(pay_load) {
}
void Execute() const override {
std::cout << "SimpleCommand: See, I can do simple things like printing (" << this->pay_load_ << ")\n";
}
};
/**
* Các lớp Receiver chứa một số logic nghiệp vụ quan trọng. Chúng biết cách thực
* hiện tất cả các loại hoạt động, liên quan đến việc thực hiện một yêu cầu.
* Trên thực tế, bất kỳ lớp nào cũng có thể đóng vai trò là Receiver.
*/
class Receiver {
public:
void DoSomething(const std::string &a) {
std::cout << "Receiver: Working on (" << a << ".)\n";
}
void DoSomethingElse(const std::string &b) {
std::cout << "Receiver: Also working on (" << b << ".)\n";
}
};
/**
* Tuy nhiên, một số Command có thể ủy thác các hoạt động phức tạp hơn
* cho các đối tượng khác, được gọi là "receivers."
*/
class ComplexCommand : public Command {
/**
* @var Receiver
*/
private:
Receiver *receiver_;
/**
* Dữ liệu ngữ cảnh, được yêu cầu để khởi chạy các phương thức của Receiver.
*/
std::string a_;
std::string b_;
/**
* Các Command phức tạp có thể chấp nhận một hoặc một số đối tượng receiver
* cùng với bất kỳ dữ liệu ngữ cảnh nào thông qua phương thức khởi tạo.
*/
public:
ComplexCommand(Receiver *receiver, std::string a, std::string b) : receiver_(receiver), a_(a), b_(b) {
}
/**
* Các Command có thể ủy quyền cho bất kỳ phương thức nào của receiver.
*/
void Execute() const override {
std::cout << "ComplexCommand: Complex stuff should be done by a receiver object.\n";
this->receiver_->DoSomething(this->a_);
this->receiver_->DoSomethingElse(this->b_);
}
};
/**
* Invoker liên kết với một hoặc một số Command. Nó gửi một yêu cầu đến Command.
*/
class Invoker {
/**
* @var Command
*/
private:
Command *on_start_;
/**
* @var Command
*/
Command *on_finish_;
/**
* Khởi tạo các command.
*/
public:
~Invoker() {
delete on_start_;
delete on_finish_;
}
void SetOnStart(Command *command) {
this->on_start_ = command;
}
void SetOnFinish(Command *command) {
this->on_finish_ = command;
}
/**
* Invoker không phụ thuộc vào các lớp command. Invoker chuyển một yêu cầu
* đến receiver gián tiếp, bằng cách thực hiện một command.
*/
void DoSomethingImportant() {
std::cout << "Invoker: Does anybody want something done before I begin?\n";
if (this->on_start_) {
this->on_start_->Execute();
}
std::cout << "Invoker: ...doing something really important...\n";
std::cout << "Invoker: Does anybody want something done after I finish?\n";
if (this->on_finish_) {
this->on_finish_->Execute();
}
}
};
/**
* Mã client có thể tham số hóa một invoker bằng bất kỳ lệnh nào.
*/
int main() {
Invoker *invoker = new Invoker;
invoker->SetOnStart(new SimpleCommand("Say Hi!"));
Receiver *receiver = new Receiver;
invoker->SetOnFinish(new ComplexCommand(receiver, "Send email", "Save report"));
invoker->DoSomethingImportant();
delete invoker;
delete receiver;
return 0;
}
Kết quả
Invoker: Does anybody want something done before I begin?
SimpleCommand: See, I can do simple things like printing (Say Hi!)
Invoker: ...doing something really important...
Invoker: Does anybody want something done after I finish?
ComplexCommand: Complex stuff should be done by a receiver object.
Receiver: Working on (Send email.)
Receiver: Also working on (Save report.)
Để lại một bình luận