Get Even More Visitors To Your Blog, Upgrade To A Business Listing >>

C# - Design Patterns - Chain of Responsibility

Olá a  todos! Seguindo a proposta de padrões de projeto com C#, falaremos hoje sobre o padrão comportamental Chain of Responsibility. Para ver outros padrões que já visitamos por aqui consulte esse link. Esse tema foi tratado de forma brilhante aqui.


Chain of Responsibility


O padrão de projeto Chain of Responsibility é um padrão de design comportamental que permite passar uma solicitação ao longo de uma cadeia de objetos até que um deles a trate. Cada objeto na cadeia tem a chance de tratar a solicitação. É útil quando há múltiplos objetos que podem responder a uma solicitação e você não sabe antecipadamente qual objeto será o responsável.


No C#, a implementação deste padrão envolve a definição de uma interface para as solicitações, criação de classes concretas para tratar as solicitações e definição de uma lógica de encadeamento entre essas classes. Ao receber uma solicitação, cada objeto na cadeia verifica se pode tratá-la e, se não puder, passa a solicitação para o próximo objeto na cadeia.


Quando podemos usar?


O Chain of Responsibility deve ser usado em situações onde:

  • Existe múltiplos objetos que podem responder a uma solicitação e você não sabe antecipadamente qual objeto será o responsável.
  • Você quer evitar um acoplamento rígido entre as solicitações e seus tratadores, permitindo que o número e o tipo de tratadores sejam especificados dinamicamente.
  • Você quer evitar o envio de uma solicitação a objetos desnecessários, tornando o processo de tratamento mais eficiente.
  • Você deseja que vários objetos tenham a chance de tratar a solicitação, sem que seja necessário especificar explicitamente a ordem em que os objetos serão verificados.

Além disso, o Chain of Responsibility é especialmente útil quando existe múltiplos tratadores que podem ser adicionados ou removidos ao longo do tempo, sem que seja necessário alterar a classe que envia as solicitações.


Exemplo


No exemplo abaixo, a interface IRequest representa as solicitações e é implementada pela classe concreta PurchaseRequest. Esta classe representa uma solicitação de compra.


As três classes concretas de tratadores Director, VicePresident e President representam três níveis de aprovação para a solicitação de compra. Cada classe herda da classe abstrata Approver e implementa o método ProcessRequest para tratar a solicitação. O método verifica se o valor da solicitação é menor do que o seu limite de aprovação e, se for, aprova a solicitação. Se não puder aprovar a solicitação, ele passa para o próximo tratador na cadeia, se houver.


Na classe Program, criamos a cadeia de tratadores, definindo qual tratador é o sucessor de outro tratador na cadeia. Em seguida, enviamos três solicitações de compra diferentes para a cadeia, onde são processadas pelos tratadores na ordem correta, até que seja encontrado o tratador responsável ou a cadeia chegue ao fim.

    
using System;

// Define a interface para as solicitações
interface IRequest
{
int Amount { get; set; }
}

// Define a classe concreta para as solicitações
class PurchaseRequest : IRequest
{
public int Amount { get; set; }
public PurchaseRequest(int amount)
{
this.Amount = amount;
}
}

// Define a classe abstrata para os tratadores
abstract class Approver
{
protected Approver successor;
public void SetSuccessor(Approver successor)
{
this.successor = successor;
}
public abstract void ProcessRequest(IRequest request);
}

// Define as classes concretas para os tratadores
class Director : Approver
{
public override void ProcessRequest(IRequest request)
{
if (request.Amount {
Console.WriteLine("A solicitação de compra de R$" + request.Amount + " foi aprovada pelo Diretor.");
}
else if (successor != null)
{
successor.ProcessRequest(request);
}
}
}

class VicePresident : Approver
{
public override void ProcessRequest(IRequest request)
{
if (request.Amount {
Console.WriteLine("A solicitação de compra de R$" + request.Amount + " foi aprovada pelo Vice-Presidente.");
}
else if (successor != null)
{
successor.ProcessRequest(request);
}
}
}

class President : Approver
{
public override void ProcessRequest(IRequest request)
{
if (request.Amount >= 25000)
{
Console.WriteLine("A solicitação de compra de R$" + request.Amount + " foi aprovada pelo Presidente.");
}
}
}

class Program
{
static void Main(string[] args)
{
// Cria a cadeia de tratadores
Approver director = new Director();
Approver vicePresident = new VicePresident();
Approver president = new President();

director.SetSuccessor(vicePresident);
vicePresident.SetSuccessor(president);

// Envia as solicitações
IRequest request = new PurchaseRequest(2000);
director.ProcessRequest(request);

request = new PurchaseRequest(20000);
director.ProcessRequest(request);

request = new PurchaseRequest(50000);
director.ProcessRequest(request);

Console.ReadKey();
}
}

Conclusão

Como podemos perceber o padrão que abordamos aqui permite que vários objetos tentem responder a uma solicitação sem que a classe que envia essa solicitação saiba qual objeto é o responsável, criando uma cadeia de tratadores, onde cada tratador tem a oportunidade de processar a solicitação e passá-la para o próximo tratador na cadeia, se não puder tratá-la.

  • Documentação do C#
  • No Wikipédia
  • Chain of Responsibility


This post first appeared on PROGRAMERO, please read the originial post: here

Share the post

C# - Design Patterns - Chain of Responsibility

×

Subscribe to Programero

Get updates delivered right to your inbox!

Thank you for your subscription

×