Chain of Responsibility em C++
O Chain of Responsibility é um padrão de projeto comportamental que permite passar a solicitação ao longo da cadeia de handlers em potencial até que um deles lide com a solicitação.
O padrão permite que vários objetos tratem a solicitação sem acoplar a classe remetente às classes concretas dos destinatários. A cadeia pode ser composta dinamicamente em tempo de execução com qualquer handler que siga uma interface de handler padrão.
Complexidade:
Popularidade:
Exemplos de uso: O padrão Chain of Responsibility não é um padrão frequente em um programa C++, pois é relevante apenas quando o código opera com cadeias de objetos.
Identificação: O padrão é reconhecível pelos métodos comportamentais de um grupo de objetos que indiretamente chamam os mesmos métodos em outros objetos, enquanto todos os objetos seguem a interface comum.
Exemplo conceitual
Este exemplo ilustra a estrutura do padrão de projeto Chain of Responsibility. Ele se concentra em responder a estas perguntas:
- De quais classes ele consiste?
- Quais papéis essas classes desempenham?
- De que maneira os elementos do padrão estão relacionados?
main.cc: Exemplo conceitual
/** * The Handler interface declares a method for building the chain of handlers. * It also declares a method for executing a request. */ class Handler { public: virtual Handler *SetNext(Handler *handler) = 0; virtual std::string Handle(std::string request) = 0; }; /** * The default chaining behavior can be implemented inside a base handler class. */ class AbstractHandler : public Handler { /** * @var Handler */ private: Handler *next_handler_; public: AbstractHandler() : next_handler_(nullptr) { } Handler *SetNext(Handler *handler) override { this->next_handler_ = handler; // Returning a handler from here will let us link handlers in a convenient // way like this: // $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 {}; } }; /** * All Concrete Handlers either handle a request or pass it to the next handler * in the chain. */ 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); } } }; /** * The client code is usually suited to work with a single handler. In most * cases, it is not even aware that the handler is part of a chain. */ 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"; } } } /** * The other part of the client code constructs the actual chain. */ int main() { MonkeyHandler *monkey = new MonkeyHandler; SquirrelHandler *squirrel = new SquirrelHandler; DogHandler *dog = new DogHandler; monkey->SetNext(squirrel)->SetNext(dog); /** * The client should be able to send a request to any handler, not just the * first one in the chain. */ 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; } Output.txt: Resultados da execução
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.