.NET - O padrão de projeto Facade (VB .NET/C#)


O padrão de projeto Facade é um padrão estrutural que fornece uma interface unificada para um conjunto de interfaces em um subsistema. O padrão Facade define uma interface de nível mais elevado que faz com que o subsistema fique mais fácil de ser utilizado.(GoF - Gang of Four)

Nota: Padrões de projeto estruturais são padrões que lidam com as estruturas do projeto, facilitando a comunicação entre suas entidades. Dessa forma eles tratam a maneira como objetos e classes estão dispostos em um projeto a fim de formar estruturas mais complexas.

De forma mais simples podemos dizer que o padrão Facade tem como objetivo esconder a complexidade de um sistema expondo apenas as interfaces que o cliente precisa enxergar. Com isso o sistema fica mais simples e fornece uma coleção de métodos mais fáceis de entender.

O diagrama de classes para o padrão Facade usando a notação UML é mostrado na figura abaixo:

Obs: A Unified Modeling Language (UML) é uma linguagem de modelagem não proprietária de terceira geração. A UML não é uma metodologia de desenvolvimento, o que significa que ela não diz para você o que fazer primeiro e em seguida ou como projetar seu sistema, mas ela lhe auxilia a visualizar seu desenho e a comunicação entre objetos.( http://pt.wikipedia.org/wiki/UML)

Classes/Objetos participantes do padrão:
  1. Facade - Conhece quais classes do subsistema são responsáveis por uma solicitação.
    Delega os pedidos de clientes a objetos apropriados do subsistema.
  2. SubSistema - Implementa as funcionalidades do subsistema; Trata o trabalho atribuído
    pelo objeto Facade e Não têm conhecimento do Facade e não mantêm nenhuma referência a ele.

Vantagens em usar o padrão Facade:

Quando usar o padrão Facade ?

Implementando o padrão de projeto Facade

Para implementar o padrão Facade vamos usar um exemplo de um sistema de Concessão de Crédito representado pela aplicação PadraoProjetoFacade que fornece uma interface simplificada para um grande subsistema de classes que devem realizar as operações de verificação de limite de crédito do cliente, consulta ao SERASA e consulta ao CADIN para definir se o crédito deverá ou não ser concedido.

Neste cenário iremos ter as seguintes classes:

  1. Cliente - Representa um cliente;
  2. Serasa - Classe que consulta o Serasa e indica se o cliente possui restrição;
  3. Cadin - Classe que consulta o Cadin e indica se o cliente esta inscrito no CADIN;
  4. LimiteCredito - Classe que determina se cliente possui limite de crédito para a operação desejada;
  5. Facade - Representa a nossa interface única;

A seguir temos o diagrama das classes usadas :

Vamos agora criar as classes e verificar o seu funcionamento.

Eu vou usar o Visual Studio 2012 Express Edition e criar uma aplicação Console chamada PadraoProjetoFacade;

Obs: Estou disponibilizando também o código para VB .NET criado no Visual Studio 2012 Express Edition

No menu Project clique em Add Class e informe o nome Cliente.cs/Cliente.vb e a seguir digite o código da classe Cliente conforme abaixo:

Na classe Cliente definimos apenas o nome do cliente;

namespace PadraoProjetoFacade
{
    public class Cliente
    {
        public string Nome { get; set; }
        public Cliente(string nome)
        {
            Nome = nome;
        }
    }
}
Public Class Cliente
	Public Property Nome() As String
		Get
			Return m_Nome
		End Get
		Set
			m_Nome = Value
		End Set
	End Property
	Private m_Nome As String
	Public Sub New(_nome As String)
		Nome = _nome
	End Sub
End Class
C# VB .NET

A seguir vamos declarar a classe LimiteCredido chamada conforme o código a seguir:

Estamos definindo um valor limite de R$ 200.000,00 para o cliente;

using System;

namespace PadraoProjetoFacade
{
    public class LimiteCredito
    {
        public bool PossuiLimiteCredito(Cliente cliente, double valor)
        {
            Console.WriteLine("Verificando o limite de crédito do cliente " + cliente.Nome);
            if (valor > 200000.00)
                return false;
            else
                return true;
        }
    }
}
C#
Public Class LimiteCredito
    Public Function PossuiLimiteCredito(cliente As Cliente, valor As Double) As Boolean
        Console.WriteLine("Verificando o limite de crédito do cliente " & Convert.ToString(cliente.Nome))
        If valor > 200000.0 Then
            Return False
        Else
            Return True
        End If
    End Function
End Class
VB .NET

Agora vamos criar a classe Serasa que retorna um valor boleano indicando se o cliente possui restrições:

Por padrão estamos retornando o valor false por questão de simplicidade;

using System;

namespace PadraoProjetoFacade
{
    public class Serasa
    {
        public bool EstaNoSerasa(Cliente cliente)
        {
            Console.WriteLine("Verificando SERASA do cliente " + cliente.Nome);
            return false;
        }
    }
}
C#
Public Class Serasa
    Public Function EstaNoSerasa(cliente As Cliente) As Boolean
        Console.WriteLine("Verificando SERASA do cliente " & Convert.ToString(cliente.Nome))
        Return False
    End Function
End Class
VB .NET

Vamos criar a classe Cadin que indica se cliente esta inscrito no CADIN;

Por padrão estamos retornando o valor false por questão de simplicidade;

using System;
namespace PadraoProjetoFacade
{
    public class Cadin
    {
        public bool EstaNoCadin(Cliente cliente)
        {
            Console.WriteLine("Verificando o CADIN para o cliente " + cliente.Nome);
            return false;
        }
    }
}
C#
Public Class Cadin
    Public Function EstaNoCadin(cliente As Cliente) As Boolean
        Console.WriteLine("Verificando o CADIN para o cliente " & Convert.ToString(cliente.Nome))
        Return False
    End Function
End Class
VB .NET

Por fim vamos criar a classe Facade que implementa o padrão Facade:

Nesta classe temos o método ConcederEmprestimo:

using System;

namespace PadraoProjetoFacade
{
    public class Facade
    {
        private LimiteCredito limite = new LimiteCredito();
        private Serasa serasa = new Serasa();
        private Cadin cadin = new Cadin();

        public bool ConcederEmprestimo(Cliente cliente, double valor)
        {
            Console.WriteLine("{0} esta pleitando um empréstimo no valor de {1:C}\n",cliente.Nome, valor);

            bool ConcederEmprestimo = true;

            if (serasa.EstaNoSerasa(cliente))
            {
                // Verifica o Serasa
                Console.WriteLine("Cliente " + cliente.Nome + " possui restrição no SERASA");
                ConcederEmprestimo = false;
            }
            else if (cadin.EstaNoCadin(cliente))
            {
                // Verifica o Cadin
                Console.WriteLine("Cliente " + cliente.Nome + " possui restrição no CADIN");
                ConcederEmprestimo = false;
            }
            else if (!limite.PossuiLimiteCredito(cliente,valor))
            {
                //verifica se o cliente tem limite de crédito para o valor requerido
                Console.WriteLine("O Cliente {0} possui limite de crédido inferior a {1:C}\n ", cliente.Nome, valor);
                ConcederEmprestimo = false;
            }
            //true-concede  false-nega
            return ConcederEmprestimo;
        }
    }
}
C#
Public Class Facade
		Private limite As New LimiteCredito()
		Private serasa As New Serasa()
		Private cadin As New Cadin()

		Public Function ConcederEmprestimo(cliente As Cliente, valor As Double) As Boolean
			Console.WriteLine("{0} esta pleitando um empréstimo no valor de {1:C}" & vbLf, cliente.Nome, valor)

			Dim ConcederEmprestimo As Boolean = True

			If serasa.EstaNoSerasa(cliente) Then
				' Verifica o Serasa
				Console.WriteLine("Cliente " & Convert.ToString(cliente.Nome) & " possui restrição no SERASA")
				ConcederEmprestimo = False
			ElseIf cadin.EstaNoCadin(cliente) Then
				' Verifica o Cadin
				Console.WriteLine("Cliente " & Convert.ToString(cliente.Nome) & " possui restrição no CADIN")
				ConcederEmprestimo = False
			ElseIf Not limite.PossuiLimiteCredito(cliente, valor) Then
				'verifica se o cliente tem limite de crédito para o valor requerido
				Console.WriteLine("O Cliente {0} possui limite de crédido inferior a {1:C}" & vbLf & " ", cliente.Nome, valor)
				ConcederEmprestimo = False
			End If
			'true-concede  false-nega
			Return ConcederEmprestimo
		End Function
	End Class
VB .NET

A classe Facade utiliza o padrão Facade e simplifica a interface com o usuário pois o mesmo cria uma instância da classe Facade e chama o método ConcederEmprestimo que esconde a complexidade de consultar o SERASA, CADIN e calcular o limite de crédito.

Para testar a implementação vamos definir o código na classe Program.cs/Module1.vb :

Module Module1

    Sub Main()

        ' Cria uma instância do Facade
        Dim concedeCredito As New Facade()

        ' Cria uma instância de um  novo Cliente informando o nome
        Dim cliente1 As New Cliente("Macoratti")

        'Utiliza o Facade para verificar condições de concessão ou não
        Dim resultado As Boolean = concedeCredito.ConcederEmprestimo(cliente1, 199000.0)

        'exibe o resultado
        Console.WriteLine("O empréstimo pleiteado pelo cliente " + cliente1.Nome & " foi  " & (If(resultado, "Aprovado", "Negado")))

        'aguarda
        Console.ReadKey()

    End Sub

End Module
VB .NET
using System;

namespace PadraoProjetoFacade
{
    class Program
    {
        static void Main(string[] args)
        {
            // Cria uma instância do Facade
            Facade concedeCredito = new Facade();

            // Cria uma instância de um  novo Cliente informando o nome
            Cliente cliente1 = new Cliente("Macoratti");

            //Utiliza o Facade para verificar condições de concessão ou não
            bool resultado = concedeCredito.ConcederEmprestimo(cliente1, 199000.00);

            //exibe o resultado
            Console.WriteLine("O empréstimo pleiteado pelo cliente " + cliente1.Nome + " foi  " + (resultado ? "Aprovado" : "Negado"));

            //aguarda
            Console.ReadKey();
        }
    }
}	
C#

O projeto é bem simples mas ilustra a atuação do Facade.

Executando o projeto Console e definindo um valor de concessão para R$ 300.000,00 iremos obter:

Executando o projeto Console novamente e definindo um valor de concessão para R$ 199.000,00 iremos obter:

Pegue a solução completa aqui: PadraoProjetoFacade.zip /  PadraoProjetoFacadeVB.zip (Abra no Visual Studio 2012 Express)

1Pe 2:11 Amados, exorto-vos, como a peregrinos e forasteiros, que vos abstenhais das concupiscências da carne, as quais combatem contra a alma;
1Pe 2:12
tendo o vosso procedimento correto entre os gentios, para que naquilo em que falam mal de vós, como de malfeitores, observando as vossas boas obras, glorifiquem a Deus no dia da visitação.

Referências:


José Carlos Macoratti