O Chain of responsability é um poderoso pattern que permite de forma simples mas altamente parametrizável de ter uma forma de delegação de contexto de um pedido baseado em determinados parametros. No limite estes parametros podem até ser classes com lógica própria.
A definição do GoF diz: “Evitar acoplar o emitente de um pedido do seu receptor dando ao objecto mais de uma forma de tratar o pedido. Listar sequencialmente os objectos de pedido e passar o pedido através dessa lista (ou corrente de objectos) até que um deles consiga tratar o pedido”.
No exemplo (a que me obriguei sempre de fazer neste blog), temos uma central de compras com 4 items a ser adquiridos: PDA - 350€, Servidor - 15000€, Carro - 30000€ e Novas Instalações - 1000000€. Nesta empresa virtual existem níveis de autorização conforme a categoria ou função dos colaboradores, assim temos: Chefe Serviço aprova até 5000€, Director aprova até 25000€, Administrador aprova até 100000€ e para cima disto terá de existir uma decisão do comité executivo.
Enjoy.
1: using System;
2: // Aplicação de Teste
3: class MainApp
4: { 5: static void Main()
6: { 7: // Setup
8: ChefeServico chefeServico = new ChefeServico();
9: DirectorCompras director = new DirectorCompras();
10: Administrador administrador = new Administrador();
11: chefeServico.SetBoss(director);
12: director.SetBoss(administrador);
13:
14: // Gerar ordens de compra
15: Compra minhaCompra = new Compra(1, 350.00, "PDA");
16: chefeServico.ProcessarCompra(minhaCompra);
17:
18: minhaCompra = new Compra(2, 15000.00, "Novo Servidor");
19: chefeServico.ProcessarCompra(minhaPara quem já quis desenvolver workflows este é um Pattern conhecido.
20: O Chain of responsability é um poderoso pattern que permite de forma simples mas altamente parametrizável de ter uma forma de delegação de contexto baseado em determinados parametros.
21: No limite estes parametros podem até ser classes com lógica própria.
22: No exemplo (a que me obriguei sempre de fazer neste blog), temos uma central de compras com 4 items a ser adquiridos:
23: PDA - 350€, Servidor - 15000€, Carro - 30000€ e Novas Instalações - 1000000€. Neste empresa virtual existem níveis de autorização conforme a categoria ou função dos colaboradores, assim temos:
24: Chefe Serviço aprova até 5000€, Director aprova até 25000€, Administrador aprova até 100000€ e para cima disto terá de existir uma decisão do comité executivo.
25: Compra);
26:
27: minhaCompra = new Compra(3, 30000.00, "Carro");
28: chefeServico.ProcessarCompra(minhaCompra);
29:
30: minhaCompra = new Compra(4, 1000000.00, "Novas Instalações");
31: chefeServico.ProcessarCompra(minhaCompra);
32:
33: // Aguardar
34: Console.Read();
35: }
36: }
37:
38: // "Handler"
39: // Aprovador
40: abstract class Aprovador
41: { 42: protected Aprovador boss;
43: public void SetBoss(Aprovador boss)
44: { 45: this.boss = boss;
46: }
47: public abstract void ProcessarCompra(Compra compra);
48: }
49:
50: // "ConcreteHandler"
51: // ChefeServico
52: class ChefeServico : Aprovador
53: { 54: public override void ProcessarCompra(Compra compra)
55: { 56: if (compra.Valor < 10000.0)
57: { 58: Console.WriteLine("{0} - #{1}. Aprovada por {2}.", compra.Descricao, compra.Numero, this.ToString() ); 59: }
60: else if (boss != null)
61: { 62: boss.ProcessarCompra(compra);
63: }
64: }
65: }
66:
67: // "ConcreteHandler"
68: // DirectorCompras
69: class DirectorCompras : Aprovador
70: { 71: public override void ProcessarCompra(Compra compra)
72: { 73: if (compra.Valor < 25000.0)
74: { 75: Console.WriteLine("{0} - #{1}. Aprovada por {2}.", compra.Descricao, compra.Numero, this.ToString() ); 76: }
77: else if (boss != null)
78: { 79: boss.ProcessarCompra(compra);
80: }
81: }
82: }
83:
84: // "ConcreteHandler"
85: class Administrador : Aprovador
86: { 87: public override void ProcessarCompra(Compra compra)
88: { 89: if (compra.Valor < 100000.0)
90: { 91: Console.WriteLine("{0} - #{1}. Aprovada por {2}.", compra.Descricao, compra.Numero, this.ToString() ); 92: }
93: else
94: { 95: Console.WriteLine("{0} - #{1}. Necessita de uma reunião de comissão executiva!", compra.Descricao, compra.Numero ); 96: }
97: }
98: }
99:
100: // Request details
101: class Compra
102: { 103: private int numero;
104: private double valor;
105: private string descricao;
106:
107: // Constructor
108: public Compra(int numero, double valor, string descricao)
109: { 110: this.numero = numero;
111: this.valor = valor;
112: this.descricao = descricao;
113: }
114:
115: // Properties
116: public double Valor
117: { 118: get{ return valor; } 119: set{ valor = value; } 120: }
121:
122: public string Descricao
123: { 124: get{ return descricao; } 125: set{ descricao = value; } 126: }
127:
128: public int Numero
129: { 130: get{ return numero; } 131: set{ numero = value; } 132: }
133: }