Nội dung
Chain of Responsibility là mẫu thiết kế hành vi cho phép chuyển yêu cầu dọc theo chuỗi các trình xử lý tiềm năng cho đến khi một trong số họ xử lý yêu cầu.
Mẫu cho phép nhiều đối tượng xử lý yêu cầu mà không cần ghép lớp người gửi (sender) với các lớp cụ thể của người nhận (receiver). Chuỗi có thể được tạo động trong thời gian chạy với bất kỳ trình xử lý nào tuân theo giao diện trình xử lý tiêu chuẩn.
Cách sử dụng
Ví dụ sử dụng: Mẫu Chain of Responsibility không phải là xuất hiện thường xuyên trong chương trình C++ vì nó chỉ phù hợp khi mã hoạt động với chuỗi đối tượng.
Nhận dạng: Mẫu có thể nhận biết được bằng các phương thức hành vi của một nhóm đối tượng gọi gián tiếp các phương thức giống nhau trong các đối tượng khác, trong khi tất cả các đối tượng tuân theo giao diện chung.
Chương trình mẫu
main.cpp
/**
* Giao diện Handler khai báo phương thức để tạo chuỗi các trình xử lý.
* Nó cũng khai báo một phương thức để xử lý yêu cầu.
*/
class Handler {
public:
virtual Handler *SetNext(Handler *handler) = 0;
virtual std::string Handle(std::string request) = 0;
};
/**
* Hành vi mặc định cho chuỗi có thể được thực hiện
* bên trong một lớp xử lý cơ sở.
*/
class AbstractHandler : public Handler {
/**
* @var Handler
*/
private:
Handler *next_handler_;
public:
AbstractHandler() : next_handler_(nullptr) {
}
Handler *SetNext(Handler *handler) override {
this->next_handler_ = handler;
// Việc trả lại một trình xử lý ở đây sẽ cho phép chúng ta
// liên kết các trình xử lý theo cách thuận tiện như sau:
// $monkey->setNext($squirrel)->setNext($dog);
return handler;
}
std::string Handle(std::string request) override {
if (this->next_handler_) {
return this->next_handler_->Handle(request);
}
return {};
}
};
/**
* Tất cả Trình xử lý cụ thể hoặc xử lý một yêu cầu
* hoặc chuyển nó cho cái tiếp theo trong chuỗi.
*/
class MonkeyHandler : public AbstractHandler {
public:
std::string Handle(std::string request) override {
if (request == "Banana") {
return "Monkey: I'll eat the " + request + ".\n";
} else {
return AbstractHandler::Handle(request);
}
}
};
class SquirrelHandler : public AbstractHandler {
public:
std::string Handle(std::string request) override {
if (request == "Nut") {
return "Squirrel: I'll eat the " + request + ".\n";
} else {
return AbstractHandler::Handle(request);
}
}
};
class DogHandler : public AbstractHandler {
public:
std::string Handle(std::string request) override {
if (request == "MeatBall") {
return "Dog: I'll eat the " + request + ".\n";
} else {
return AbstractHandler::Handle(request);
}
}
};
/**
* Client làm việc với một trình xử lý duy nhất. Trong hầu hết các trường
* hợp, nó thậm chí không biết rằng trình xử lý là một phần của chuỗi.
*/
void ClientCode(Handler &handler) {
std::vector<std::string> food = {"Nut", "Banana", "Cup of coffee"};
for (const std::string &f : food) {
std::cout << "Client: Who wants a " << f << "?\n";
const std::string result = handler.Handle(f);
if (!result.empty()) {
std::cout << " " << result;
} else {
std::cout << " " << f << " was left untouched.\n";
}
}
}
/**
* Phần khác của client xây dựng chuỗi thực tế.
*/
int main() {
MonkeyHandler *monkey = new MonkeyHandler;
SquirrelHandler *squirrel = new SquirrelHandler;
DogHandler *dog = new DogHandler;
monkey->SetNext(squirrel)->SetNext(dog);
/**
* Client có thể gửi yêu cầu tới bất kỳ trình xử lý nào,
* không chỉ trình xử lý đầu tiên trong chuỗi.
*/
std::cout << "Chain: Monkey > Squirrel > Dog\n\n";
ClientCode(*monkey);
std::cout << "\n";
std::cout << "Subchain: Squirrel > Dog\n\n";
ClientCode(*squirrel);
delete monkey;
delete squirrel;
delete dog;
return 0;
}
Kết quả
Chain: Monkey > Squirrel > Dog
Client: Who wants a Nut?
Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
Monkey: I'll eat the Banana.
Client: Who wants a Cup of coffee?
Cup of coffee was left untouched.
Subchain: Squirrel > Dog
Client: Who wants a Nut?
Squirrel: I'll eat the Nut.
Client: Who wants a Banana?
Banana was left untouched.
Client: Who wants a Cup of coffee?
Cup of coffee was left untouched.
Để lại một bình luận