Facade Design Pattern

    Read the description of other patterns.

    Problem


    To minimize the dependence of the subsystems of some complex system and the exchange of information between them.

    Description


    When designing complex systems, the so-called decomposition principle, in which a complex system is divided into smaller and simpler subsystems. Moreover, the level of decomposition (its depth) is determined solely by the designer. Thanks to this approach, the individual components of the system can be developed in isolation, then integrated together. However, a problem that appears obvious at first glance arises - high connectivity of the system modules. This is manifested primarily in the large amount of information that the modules exchange with each other. In addition, for such communication, some modules must have sufficient information about the nature of other modules.

    Thus, minimizing the dependence of subsystems, as well as reducing the amount of information transmitted between them, is one of the main design tasks.

    One way to solve this problem is to use the “Facade” pattern.

    The Facade pattern provides a unified interface instead of a set of interfaces of a subsystem. The façade defines a higher-level interface that
    simplifies the use of the subsystem.

    Simply put, the “Facade” is nothing more than a certain object that accumulates a high-level set of operations for working with some complex subsystem. The facade aggregates classes that implement the functionality of this subsystem, but does not hide them. It is important to understand that the client, at the same time, does not lose the lower-level access to the subsystem classes, if it is, of course, necessary for him. The facade simplifies the implementation of some operations with the subsystem, but does not impose its use on the client.

    Practical task


    Using the “Facade” pattern, we implement a unified interface to some user authorization subsystem. The authorization subsystem itself (in this example) certainly does not pretend to be a "complex system", but it clearly displays the main advantages of the pattern.

    Class diagram


    Consider the chart. The frame of the authorization subsystem, for clarity, is highlighted in a rectangle. Facade Authorizator provides the client with a unified interface for working with the subsystem. In this case, this is just one method - authorizate (), but there could have been more. At the same time, the client can use the facade to work with the subsystem, and can directly use the classes that make up it. The authorization process itself is quite simple. Based on the username, the corresponding record in the database is searched through the DB interface. Then, the password of the found entry is compared with the password specified by the user.


    C # implementation


    There is no PgSQLDB class in the implementation code .
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Security;

    namespace Facade
    {
      //Абстрактный класс пользователя
      abstract class User
      {
        protected string username;
        protected string passwd;

        public abstract string getUserRole();

        public string getPasswdHash()
        {
          // Это строка не несет какой-либой смысловой нагрузки.
          // Безусловно, таким образом мы получаем небезопасный хеш-код пароля
          return passwd.GetHashCode().ToString();
        }
      }

      // Уточнение пользователя, в качестве пользователя по-умолчанию
      class DefaultUser : User
      {
        public DefaultUser(string username, string passwd)
        {
          this.username = username;
          this.passwd = passwd;
        }

        public override string getUserRole()
        {
          return "DEFAULT_USER";
        }
      }

      // Уточнение пользователя, в качестве администратора
      class Administrator : User
      {
        public Administrator(string username, string passwd)
        {
          this.username = username;
          this.passwd = passwd;
        }

        public override string getUserRole()
        {
          return "ADMINISTRATOR";
        }

      }

      // Интерфейс доступа к базе данных
      interface DB
      {
        User search(string username);
      }

      // Реализация интерфейса БД для SQLite
      class SQLiteDB : DB
      {
        public SQLiteDB(string filename)
        {
          // Инициализация драйвера БД
        }

       
        public User search(string username)
        {
          // Заглушка
          throw new NotImplementedException();
        }
      }

      // Фасад - авторизатор пользователей
      class Authorizator
      {
        public Authorizator()
        {
          // Инициализация авторизатора
        }

        // Авторизация пользователя
        public void authorizate(string username, string passwd)
        {
          DB db = new SQLiteDB("db.sqlite");
          User user = db.search(username);
          if (user.getPasswdHash() == passwd)
          {
            // все хорошо, пользователь опознан
          }
          else
          {
            // что-то пошло не так
            throw new SecurityException("Wrong password or username!");
          }
        }
      }
       
      class Program
      {
        static void Main(string[] args)
        {
          // Вымышленный пользователь
          string username = "Vasya";
          string passwd = "qwerty".GetHashCode().ToString();
          
          Authorizator auth = new Authorizator();
          try
          {
            auth.authorizate(username, passwd);
          }
          catch (SecurityException ex)
          {
            // Пользователь не прошел аутентификацию
          }
        }
      }
    }

    * This source code was highlighted with Source Code Highlighter.

    PS : Does not work for me for one?

    Also popular now: