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?
Program.cs: Exemplo conceitual
using System; using System.Collections.Generic; namespace RefactoringGuru.DesignPatterns.ChainOfResponsibility.Conceptual { // The Handler interface declares a method for building the chain of // handlers. It also declares a method for executing a request. public interface IHandler { IHandler SetNext(IHandler handler); object Handle(object request); } // The default chaining behavior can be implemented inside a base handler // class. abstract class AbstractHandler : IHandler { private IHandler _nextHandler; public IHandler SetNext(IHandler handler) { this._nextHandler = handler; // Returning a handler from here will let us link handlers in a // convenient way like this: // monkey.SetNext(squirrel).SetNext(dog); return handler; } public virtual object Handle(object request) { if (this._nextHandler != null) { return this._nextHandler.Handle(request); } else { return null; } } } class MonkeyHandler : AbstractHandler { public override object Handle(object request) { if ((request as string) == "Banana") { return $"Monkey: I'll eat the {request.ToString()}.\n"; } else { return base.Handle(request); } } } class SquirrelHandler : AbstractHandler { public override object Handle(object request) { if (request.ToString() == "Nut") { return $"Squirrel: I'll eat the {request.ToString()}.\n"; } else { return base.Handle(request); } } } class DogHandler : AbstractHandler { public override object Handle(object request) { if (request.ToString() == "MeatBall") { return $"Dog: I'll eat the {request.ToString()}.\n"; } else { return base.Handle(request); } } } class Client { // 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. public static void ClientCode(AbstractHandler handler) { foreach (var food in new List<string> { "Nut", "Banana", "Cup of coffee" }) { Console.WriteLine($"Client: Who wants a {food}?"); var result = handler.Handle(food); if (result != null) { Console.Write($" {result}"); } else { Console.WriteLine($" {food} was left untouched."); } } } } class Program { static void Main(string[] args) { // The other part of the client code constructs the actual chain. var monkey = new MonkeyHandler(); var squirrel = new SquirrelHandler(); var 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. Console.WriteLine("Chain: Monkey > Squirrel > Dog\n"); Client.ClientCode(monkey); Console.WriteLine(); Console.WriteLine("Subchain: Squirrel > Dog\n"); Client.ClientCode(squirrel); } } } 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.