Фасад (англ. Facade) — структурный шаблон проектирования, позволяющий скрыть сложность системы путём сведения всех возможных внешних вызовов к одному объекту, делегирующему их соответствующим объектам системы.
Это один из тех паттернов, у которого нет четкой реализации, так как она зависит от конкретной системы. В общем случае фасад осуществляет такое преобразование:
Тремя верхними блоками обозначаются три участка клиентского кода, в которых он взаимодействует с этой подсистемой. Задача фасада сделать простой, единый интерфейс, через который было бы достаточно для взаимодействия с подсистемами в рамках поставленной задачи, т.е. нам не нужно делать универсальный интерфейс, на все случаи жизни, так как это в большинстве случаев излишне и ведет к усложнению взаимодействия, увеличению времени разработки.
Фасады в Laravel
Фасад в Laravel представляет собой единую точку доступа к цельному пакету, который состоит из нескольких классов (или любой другой цельной структуре состоящей из частей). То есть, вместо того чтобы оперировать внутренними классами пакета, мы оперируем фасадом, который транслирует нужный функционал из нужных классов или классов пакета. Тем самым достигается инкапсуляция пакета, и уход от лишних зависимостей.
В формате Laravel, насколько я понял, фасад по сути, это обертка, дающая более удобный доступ к классу. Вернее, даже не к классу, а к его алиасу в IoC. То есть, позволяет сжать синтаксис вызова класса, но имеет мало общего с моим представлением о фасаде.
Laravel уже поставляется со множеством готовых фасадов, которые определены в файле config/app.php, в элементе массива aliases:
'aliases' => [ 'App' => Illuminate\Support\Facades\App::class, 'Artisan' => Illuminate\Support\Facades\Artisan::class, 'Auth' => Illuminate\Support\Facades\Auth::class, 'Blade' => Illuminate\Support\Facades\Blade::class, 'Broadcast' => Illuminate\Support\Facades\Broadcast::class, 'Bus' => Illuminate\Support\Facades\Bus::class, 'Cache' => Illuminate\Support\Facades\Cache::class, 'Config' => Illuminate\Support\Facades\Config::class, 'Cookie' => Illuminate\Support\Facades\Cookie::class, 'Crypt' => Illuminate\Support\Facades\Crypt::class, 'DB' => Illuminate\Support\Facades\DB::class, 'Eloquent' => Illuminate\Database\Eloquent\Model::class, 'Event' => Illuminate\Support\Facades\Event::class, 'File' => Illuminate\Support\Facades\File::class, 'Gate' => Illuminate\Support\Facades\Gate::class, 'Hash' => Illuminate\Support\Facades\Hash::class, 'Lang' => Illuminate\Support\Facades\Lang::class, 'Log' => Illuminate\Support\Facades\Log::class, 'Mail' => Illuminate\Support\Facades\Mail::class, 'Notification' => Illuminate\Support\Facades\Notification::class, 'Password' => Illuminate\Support\Facades\Password::class, 'Queue' => Illuminate\Support\Facades\Queue::class, 'Redirect' => Illuminate\Support\Facades\Redirect::class, 'Redis' => Illuminate\Support\Facades\Redis::class, 'Request' => Illuminate\Support\Facades\Request::class, 'Response' => Illuminate\Support\Facades\Response::class, 'Route' => Illuminate\Support\Facades\Route::class, 'Schema' => Illuminate\Support\Facades\Schema::class, 'Session' => Illuminate\Support\Facades\Session::class, 'Storage' => Illuminate\Support\Facades\Storage::class, 'URL' => Illuminate\Support\Facades\URL::class, 'Validator' => Illuminate\Support\Facades\Validator::class, 'View' => Illuminate\Support\Facades\View::class ],
Соответственно все эти фасады мы можем использовать в своих классах, предворительно подключив их с помщью конструкции use
, после чего идет имя фасада. Пример:
use Auth;
Создание фасадов в Laravel
Создать фасад в вашем приложении можно за три этапа:
Посмотрим на следующий пример. Здесь определён класс PaymentGateway\Payment
.
namespace PaymentGateway; class Payment { public function process() { // } }
Этот класс может находиться в вашем каталоге app/libs или в любом другом каталоге, который добавлен в автозагрузку Composer.
Нам нужно, чтобы этот класс извлекался из контейнера IoC, так что давайте добавим для него привязку (binding):
App::bind('payment', function () { return new \PaymentGateway\Payment; });
Самое лучшее место для регистрации этой связки — новый поставщик услуг, который мы назовём PaymentServiceProvider
и в котором мы создадим метод register()
, содержащий код выше. После этого вы можете настроить Laravel для загрузки этого поставщика в файле config/app.php.
Дальше пишем класс фасада:
use Illuminate\Support\Facades\Facade; class Payment extends Facade { protected static function getFacadeAccessor() { return 'payment'; } }
Наконец, по желанию можно добавить псевдоним (alias) для этого фасада в массив aliases файла настроек config/app.php — тогда мы сможем вызывать метод process() класса Payment:
Payment::process();
PHP
/** * Реализации отдельных частей компьютера. * У каждого метода классов имеется какая-то реализация, в данном примере она опущена. */ /** * Class CPU, отвечает за работу процессора */ class CPU { public function freeze() {} public function jump($position) {} public function execute() {} } /** * Class Memory, отвечает за работу памяти */ class Memory { const BOOT_ADDRESS = 0x0005; public function load($position, $data) {} } /** * Class HardDrive, отвечает за работу жёсткого диска */ class HardDrive { const BOOT_SECTOR = 0x001; const SECTOR_SIZE = 64; public function read($lba, $size) {} } /** * Пример шаблона "Фасад" * В качестве унифицированного объекта выступает Компьютер. * За этим объектом будут скрыты, все детали работы его внутренних частей. */ class Computer { protected $cpu; protected $memory; protected $hardDrive; /** * Computer constructor. * Инициализируем части */ public function __construct() { $this->cpu = new CPU(); $this->memory = new Memory(); $this->hardDrive = new HardDrive(); } /** * Упрощённая обработка поведения "запуск компьютера" */ public function startComputer() { $cpu = $this->cpu; $memory = $this->memory; $hardDrive = $this->hardDrive; $cpu->freeze(); $memory->load( $memory::BOOT_ADDRESS, $hardDrive->read($hardDrive::BOOT_SECTOR, $hardDrive::SECTOR_SIZE) ); $cpu->jump($memory::BOOT_ADDRESS); $cpu->execute(); } } /** * Пользователям компьютера предоставляется Фасад (компьютер), * который скрывает все сложность работы с отдельными компонентами. */ $computer = new Computer(); $computer->startComputer();
Фасады на JavaScript
Назначение фасада в JavaScript заключается в предоставлении интерфейса, содержащего логику работы с несколькими подсистемами. Используется для того, чтобы обернуть некоторую структуру в одну функцию, освободив клиентский код от работы с деталями
Использование фасада выглядит примерно так:
function facadePattern(param) { object1 = new Object1(); object2 = new Object2(); object3 = new Object3(); // some logic... }
--