Фасад (Facade) — шаблон проектирования

24 января 2020
Шаблон предлагает упрощение работы со сложными структурами (API, классы, наборы функций) с  помощью класса-фасада, который скрывает трудоёмкие процессы и предоставляет клиентскому коду более простые методы работы.

Фасад позволяет снизить зависимость клиентского кода от частообновляемых систем. Вместо прямого использование внешних библиотек клиентским кодом, вводится прослойка в виде класса-фасада. В случае критических изменений в методах из внешних библиотек, нам придётся вносить изменения, вероятнее, не в каждом месте клиентского кода, где использовались бы методы библиотек, а только в классе-фасаде. 

Пример задачи: упростить получение количества заказов пользователя на Битриксе.

Код реализации паттерна на языке PHP. Скачать исходники (ZIP, 2 Кб)



Чтобы узнать количество заказов у пользователя, в Битриксе нужно:
  1. Подключить модуль «Интернет-магазин»
  2. Запросить список заказов пользователя через метод выборки заказов \Bitrix\Sale\Order::getList
  3. В метод выборки с помощью класса \Bitrix\Main\Entity\ExpressionField добавить вычисляемое поле NUMBER_ORDERS, чтобы вместо массива заказов получить количество заказов.

По итогу вся конструкция примет монструозный вид:
//Подключаем модуль "Интернет-магазин"
\Bitrix\Main\Loader::includeModule('sale');

$userId = 1;

//Получаем количество заказов пользователя
$countOrders = 0;
$dbOrders = \Bitrix\Sale\Order::getList(array(
    'filter' => array('USER_ID' => $userId),
    'group' => array('COUNT' => 'USER_ID'),
    'select' => array('NUMBER_ORDERS'),
    'runtime' => array(
        new \Bitrix\Main\Entity\ExpressionField('NUMBER_ORDERS', 'COUNT(*)')
    )
));
if ($arOrders = $dbOrders->fetch()) {
    $countOrders = (int)$arOrders['NUMBER_ORDERS'];
}

echo 'Количество заказов пользователя: '.$countOrders.' шт.';

В клиентском коде подобные конструкции писать обременительно, поэтому требуется упрощение. В этом деле нам как раз и поможет шаблон Фасад.

user_orders.class.php 

Файл содержит класс UserOrders, состоящий из одного метода получения количества заказов пользователя getCount($userId). Внутри метода находится вся та монструозная часть, описанная выше. Но теперь она скрыта от клиентского кода за классом-фасадом UserOrders.

Гипотетически, класс может содержать множество других методов, которые упрощают взаимодействие с объёмными структурами и сложными методами, просто в рамках данной статьи и демонстрации примера мною рассматривается только один метод.
<?php

/**
 * Класс для работы с заказами пользователя
 */
class UserOrders
{
    /**
     * Возвращает количество заказов пользователя
     * @param int $userId - ID пользователя
     * @return int
     */
    public static function getCount($userId)
    {
        $countOrders = 0;

        //Подключаем модуль "Интернет-магазин"
        \Bitrix\Main\Loader::includeModule('sale');

        //Получаем количество заказов пользователя
        $dbOrders = \Bitrix\Sale\Order::getList(array(
            'filter' => array('USER_ID' => $userId),
            'group' => array('COUNT' => 'USER_ID'),
            'select' => array('NUMBER_ORDERS'),
            'runtime' => array(
                new \Bitrix\Main\Entity\ExpressionField('NUMBER_ORDERS', 'COUNT(*)')
            )
        ));
        if ($arOrders = $dbOrders->fetch()) {
            $countOrders = (int)$arOrders['NUMBER_ORDERS'];
        }

        return $countOrders;
    }
}

?>

test.php

Тестовый скрипт, где с помощью метода UserOrders::getCount($userId) происходит получение количества заказов пользователя, а затем это значение выводится на экран. Как видим, теперь для получения данных вместо 12 строчек нужно написать лишь одну.
<?php
define("NO_KEEP_STATISTIC", true); //Отключаем статистику Битрикса
define("NO_AGENT_CHECK", true);  //Отключение выполнения любых агентов

//Подключаем движок Битрикса
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");

//Подключаем класс для работы с заказами пользователя
require_once(__DIR__.'/user_orders.class.php');

$userId = 1;

//Получаем количество заказов пользователя
$countOrders = UserOrders::getCount($userId);

echo 'Количество заказов пользователя: '.$countOrders.' шт.';

?>

Результат работы скрипта test.php
Количество заказов пользователя: 65 шт.