Facade Pattern no C#

O padrão Facade Pattern (design de fachada em português) é uma maneira de fornecer classes de cliente com um meio mais fácil de interagir com as partes do seu sistema.

De acordo como Wikipédia os desenvolvedores geralmente usam este padrão de design quando um sistema é muito complexo ou difícil de entender pois tem muitas classes interdependentes ou porque seu código-fonte não está disponível. Ele oculta as complexidades do sistema maior e fornece uma interface mais simples para o cliente.

Podemos dizer que este padrão normalmente envolve uma única classe que contém um conjunto de membros exigidos pelo cliente. Esses membros acessam o sistema em nome do cliente e ocultam os detalhes de implementação.

Diagrama Estruturado


Fonte: https://refactoring.guru/pt-br/design-patterns/facade

Para exemplificar esse Pattern podemos criar uma classe chamada PetShopService que tem a finalidade de “esconder” toda a implementação que envolve a criação e manipulações de animais. Isso poderia ser feito diretamente pelo cliente, mas abstraímos toda a lógica e vamos disponibilizar somente o que o cliente precisa.

Criando as classes e interfaces

Primeiro temos que criar nossa interface. Neste exemplo, por se tratar de um PetShop, nossa interface tem o nome de IAnimal.

using System;

namespace FacadePatternPetShop
{
    internal interface IAnimal
    {
         void Walk();
         void Talk();
         void Eat();
         void GetTypeAnimal();
    }
}

Todas as nossas classes de animais deverão implementar esta interface. Então podemos criar as classes (Dog, Cat e Fish) da seguinte maneira.

using System;

namespace FacadePatternPetShop
{
    internal class Dog : IAnimal
    {
        public void Walk() { }
        public void Talk() 
        {
            Console.WriteLine("Au Au Au");
        }        public void Eat() { }
        public void GetTypeAnimal() 
        {
            Console.WriteLine(this.GetType().Name);
        }
    }

    internal class Cat : IAnimal
    {
        public void Walk() { }
        public void Talk()
        {
            Console.WriteLine("Miau Miau Miau");
        }
        public void Eat() { }
        public void GetTypeAnimal() 
        {
            Console.WriteLine(this.GetType().Name);
        }
    }

    internal class Fish : IAnimal
    {
        public void Walk() { }
        public void Talk() 
        {
            Console.WriteLine("Glup Glup Glup");
        }
        public void Eat() { }
        public void GetTypeAnimal() 
        {
            Console.WriteLine(this.GetType().Name);
        }
    }
}

Note que todas elas foram colocadas como “internal” pois queremos limitar o seu escopo.

Agora podemos criar a classe que vai ser nossa Facade. Ela vai ser a interface do usuário com toda a lógica. Esta classe sera chamada de PetShopService.

using System.Collections.Generic;
using System;

namespace FacadePatternPetShop
{
    public class PetShopService
    {
        private Dictionary<string, IAnimal> animalsOwners;

        public PetShopService(){
            animalsOwners = new Dictionary<string, IAnimal>();
        }

        public bool CreateNewRecord(string animalType, string owner){
            IAnimal newAnimal;
            switch (animalType.ToLower())
            {
                case "dog":
                    newAnimal = new Dog();
                    break;
                case "cat":
                    newAnimal = new Cat();
                    break;
                case "fish":
                    newAnimal = new Fish();
                    break;
                default:
                    return false;
            }
            animalsOwners.Add(owner, newAnimal);
            return true;
        }

        public void MakeItTalk(string owner){
            animalsOwners[owner].Talk();
        }

        public void GetAnimalType(string owner){
            animalsOwners[owner].GetTypeAnimal();
        }
    }
}

Esta classe recebe um tipo de pet (ou animal) e o nome do seu proprietário, salvando a informação em um dicionário privado. Posteriormente basta informar o seu nome do dono, e teremos os dados de seu pet. Esta classe é public exatamente por ser a fachada do código.

Para realizar um teste simplificado podemos escrever a seguinte aplicação em console.

using System;
using FacadePatternPetShop;

namespace FacadePattern
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Facade Pattern");

            var petShop = new PetShopService();
            if(petShop.CreateNewRecord("Dog", "Leandro"))
            {
                Console.WriteLine("Created Animal with success!");
            }
            
            if(petShop.CreateNewRecord("Fish", "Lisura"))
            {
                Console.WriteLine("Created Animal with success!");
            }

            petShop.MakeItTalk("Leandro");
            petShop.GetAnimalType("Lisura");
        }
    }
}
/* This will exit
Facade Pattern
Created Animal with success!
Created Animal with success!
Au Au Au
Fish
*/

Conclusão

O padrão de design de fachada (ou facade) é um meio para ocultar a complexidade de um subsistema encapsulando-o atrás de um envolucro unificador chamado de classe de fachada.

Este padrão tambem remove a necessidade de classes de cliente para gerenciar um subsistema por conta própria, resultando em menos acoplamento entre seu subsistema e as classes de cliente.

Outros ponto que valem resaltar:
– Lida com instanciação e redirecionamento de tarefas para a classe apropriada dentro do subsistema;
– Fornece classes de cliente com uma interface simplificada;
– Atua simplesmente como um ponto de entrada para um subsistema e não adiciona mais funcionalidade ao mesmo.

Qualquer dúvida ou dicas, entre em contato: leandrolt@gmail.com

Principais referências

– https://refactoring.guru/pt-br/design-patterns/facade/
– https://www.devmedia.com.br/um-pattern-em-csharp-por-dia-facade-pattern-estrutural/21752
– https://www.coursera.org/learn/design-patterns/
– https://pt.wikipedia.org/wiki/Fa%C3%A7ade

Leave a Reply

Your email address will not be published. Required fields are marked *