Design patterns: Facade

in #design-patterns7 years ago

facade2.png

In this article about the Facade design pattern , whose main task is to make the complex system available to the customer in the form of a simplified, ordered programming interface.

Description and implementation method

We implement the facade in the form of one class, which is associated with other classes of the complex system, to call the methods of the related classes. Often you can find a facade in large systems, in corporations, that is where you need a simple way to access different data.

And Facade facilitates access to various objects and hides details of the implementation, and this is good because the client does not care how exactly the system is implemented, he only wants to have access to the data that interests him.

An example of implementation can be eg a banking system in which we only have access to some system functions, transfers, account balance, etc.

Structure

The following diagram well describes the facade:

Facade1.png

It means that the facade provides one class for using software mass.

Let’s also look at another diagram below:

Facade_1.png

We see that we have different classes and every class knows the class of the facade, so it provides a simplified interface in the class to use all of these classes, the client does not need to know the exact details of the implementation.

Example

Bank facade

Let’s now see what the facade looks like in a practical example of life taken.

Our task is to create a bank account simulator, that is, we have to create an API shared with the client:

    class Program
    {
        static void Main(string[] args)
        {
            ClientAPI clientapi = new ClientAPI();
 
            clientapi.MoneySpend();
            clientapi.MoneyTransfer();
            clientapi.Account();
 
            Console.ReadKey();
        }
    }
 
    class ClientAPI
    {
        private BalllanceAccount balllanceaccount;
        private MoneySpend moneyspend;
        private MoneyTransfer moneytransfer;
 
        public ClientAPI()
        {
            balllanceaccount = new BalllanceAccount();
            moneyspend = new MoneySpend();
            moneytransfer = new MoneyTransfer();
        }
 
        public void Account()
        {
            balllanceaccount.DisplayStateAccount();
        }
 
        public void MoneySpend()
        {
            moneyspend.MoneySpendInLastMonth();
        }
 
        public void MoneyTransfer()
        {
            moneytransfer.MakeMoneyTransfer();
        }
    }
 
    class BalllanceAccount
    {
        public void DisplayStateAccount()
        {
            Console.WriteLine("View account status");
        }
    }
 
    class MoneySpend
    {
        public void MoneySpendInLastMonth()
        {
            Console.WriteLine("View the amount of money spent in the last month");
        }
    }
 
    class MoneyTransfer
    {
        public void MakeMoneyTransfer()
        {
            Console.WriteLine("Make a transfer");
        }
    }

It is much easier to use the API than to refer to individual parts of the system, also the system is much safer because the client does not have access to the entire system.

For remind the solid principles and dependency injection principle, let’s use the container from the dependency injection lesson to register class instances in the constructor and not to create them rigidly.

    class Program
    {
        static void Main(string[] args)
        {
            ClientAPI clientapi = new ClientAPI();
 
            clientapi.MoneySpend();
            clientapi.MoneyTransfer();
            clientapi.Account();
 
            Console.ReadKey();
        }
    }
 
    class ClientAPI
    {
        private IBalllanceAccount balllanceaccount;
        private IMoneySpend moneyspend;
        private IMoneyTransfer moneytransfer;
 
        private static Container container;
 
        public ClientAPI()
        {
            container = new Container();
 
            container.Register<IBalllanceAccount, BalllanceAccount>();
            container.Register<IMoneySpend, MoneySpend>();
            container.Register<IMoneyTransfer, MoneyTransfer>();
 
            ResloveMethods();
        }
 
        public void ResloveMethods()
        {
            balllanceaccount=container.Resolve<IBalllanceAccount>();
            moneyspend=container.Resolve<IMoneySpend>();
            moneytransfer= container.Resolve<IMoneyTransfer>();
        }
 
        public void Account()
        {
            balllanceaccount.DisplayStateAccount();
        }
 
        public void MoneySpend()
        {
            moneyspend.MoneySpendInLastMonth();
        }
 
        public void MoneyTransfer()
        {
            moneytransfer.MakeMoneyTransfer();
        }
    }
 
    interface IBalllanceAccount
    {
        void DisplayStateAccount();
    }
 
    class BalllanceAccount: IBalllanceAccount
    {
        public void DisplayStateAccount()
        {
            Console.WriteLine("View account status");
        }
    }
 
    interface IMoneySpend
    {
        void MoneySpendInLastMonth();
    }
 
    class MoneySpend: IMoneySpend
    {
        public void MoneySpendInLastMonth()
        {
            Console.WriteLine("View the amount of money spent in the last month");
        }
    }
 
    interface IMoneyTransfer
    {
        void MakeMoneyTransfer();
    }
 
    class MoneyTransfer: IMoneyTransfer
    {
        public void MakeMoneyTransfer()
        {
            Console.WriteLine("Make a transfer");
        }
    }
 
    public class Container
    {
        readonly Dictionary<Type, Type>
        services = new Dictionary<Type, Type>();
 
        public void Register<TRegister, TImplement>()
        {
            services.Add(typeof(TRegister), typeof(TImplement));
        }
 
        public T Resolve<T>()
        {
            Type type = services[typeof(T)];
 
            return (T)Activator.CreateInstance(type);
        }
    }

Now it is more in line with solid and dependency injection and generally with the principles of code cleanliness.

Result:

fasadaone.png

The facade of creating a car

In this example, we’ll make an example of creating a car, this example will be very similar to the previous one, let’s start with the classes that make up the individual parts of the car.

namespace Carfacade
{
    public interface ICarModel
    {
        void SetModel();
    }
 
    public class CarModel : ICarModel
    {
        public void SetModel()
        {
            Console.WriteLine(" CarModel - SetModel");
        }
    }
 
    public interface ICarEngine
    {
        void SetEngine();
    }
 
    public class CarEngine : ICarEngine
    {
        public void SetEngine()
        {
            Console.WriteLine(" CarEngine - SetEngine");
        }
    }
 
    public interface ICarBody
    {
        void SetBody();
    }
 
    public class CarBody : ICarBody
    {
        public void SetBody()
        {
            Console.WriteLine(" CarBody - SetBody");
        }
    }
 
    public interface ICarAccessories
    {
        void SetAccessories();
    }
 
    public class CarAccessories : ICarAccessories
    {
        public void SetAccessories()
        {
            Console.WriteLine(" CarAccessories - SetAccessories");
        }
    }
}

Many of these classes and the clients are not interested in their exact implementation, which is why we have a facade class that simplifies the use of these classes.

namespace Carfacade
{
    public class CarFacade
    {
        private readonly ICarAccessories accessories;
        private readonly ICarBody body;
        private readonly ICarEngine engine;
        private readonly ICarModel model;
 
        public CarFacade(ICarAccessories accessories, ICarBody body, ICarEngine engine, ICarModel model)
        {
            this.accessories = accessories;
            this.body = body;
            this.engine = engine;
            this.model = model;
        }
 
        public void CreateCompleteCar()
        {
            Console.WriteLine("Creating a Car\n");
            model.SetModel();
            engine.SetEngine();
            body.SetBody();
            accessories.SetAccessories();
 
            Console.WriteLine("\nCar creation is completed.");
        }
    }
}

By using dependency Injection principle, we inject dependencies in the constructor and create a car using only one CreateCompleteCar() method, so that the client does not have to delve into the details of the implementation and will be probably thankful for our facade class.

The call in the client looks like this:

namespace Carfacade
{
    class Program
    {
        static void Main(string[] args)
        {
            var facade = new CarFacade(new CarAccessories(), new CarBody(), new CarEngine(), new CarModel());
 
            facade.CreateCompleteCar();
 
            Console.ReadKey();
        }
    }
}

Result:

facadetwo.png

Advantages and disadvantages

Advantages

  1. Reduces the number of dependencies between the customer and the system, the whole is easier to maintain and maintenance if the customer does not use individual parts of the system.
  2. Application is split into layers, separate client and system development.
  3. The ability to block the client access to some of the system’s functionalities.

Disadvantages

  1. I don’t think there are any …

Relations with other design patterns

  1. Facade creates a new interface that simplifies the use of existing functionalities, the adapter creates an interface that works with the old interface.
  2. Flyweight shows how to make a lot of small objects, the facade shows how to make one object representing the whole system.
  3. The mediator is similar to the facade in that it simplifies the existing functionality, but differs in that the Mediator only simplifies communication between classes and Facade creates an interface, thanks to which it will simply be easier to use existing functionalities.
  4. Facade objects are often singletons, because only one object is needed in the facade pattern.

Summary

That’s all about Facade 🙂.

As you can see the Facade design pattern is very useful, now we can, for example, choose which parts of the system to share, for example our colleague in the team, so that he does not have to know what exactly he does, just that he could use it immediatly.

Link to github with the whole code from this article: https://github.com/Slaw145/FasadaTutorial

This content also you can find on my blog http://devman.pl/programtech/design-patterns-facade/

If you recognise it as useful, share it with others so that others can also use it.

Leave upvote and follow and wait for next articles :) .

In the next article, we will talk about the Composite pattern.

And NECESSERILY join the DevmanCommunity community on fb, part of the community is in one place 🙂

– site on fb: Devman.pl-Sławomir Kowalski

– group on fb: DevmanCommunity

Ask, comment underneath at the end of the post, share it, rate it, whatever you want🙂.