- Фасад (шаблон проектирования)
-
Шаблон проектирования Фасад Facade Тип: структурный
Описан в Design Patterns Да
Шаблон Facade (Фасад) — Шаблон проектирования, позволяющий скрыть сложность системы путем сведения всех возможных внешних вызовов к одному объекту, делегирующему их соответствующим объектам системы.
Содержание
Описание
Проблема
Как обеспечить унифицированный интерфейс с набором разрозненных реализаций или интерфейсов, например, с подсистемой, если нежелательно высокое связывание с этой подсистемой или реализация подсистемы может измениться?
Решение
Определить одну точку взаимодействия с подсистемой — фасадный объект, обеспечивающий общий интерфейс с подсистемой и возложить на него обязанность по взаимодействию с её компонентами. Фасад — это внешний объект, обеспечивающий единственную точку входа для служб подсистемы. Реализация других компонентов подсистемы закрыта и не видна внешним компонентам. Фасадный объект обеспечивает реализацию паттерна Устойчивый к изменениям (Protected Variations) с точки зрения защиты от изменений в реализации подсистемы.
Особенности применения
Шаблон применяется для установки некоторого рода политики по отношению к другой группе объектов. Если политика должна быть яркой и заметной, следует воспользоваться услугами шаблона Фасад. Если же необходимо обеспечить скрытность и аккуратность (прозрачность), более подходящим выбором является шаблон Заместитель (Proxy).
Примеры
JavaScript
Исходный текст на языке JavaScript/* Complex parts */ function SubSystem1() { this.method1 = function() { alert("вызван SubSystem1.method1"); }; } function SubSystem2() { this.method2 = function() { alert("вызван SubSystem2.method2"); }; this.methodB = function() { alert("вызван SubSystem2.methodB"); }; } /* Facade */ function Facade() { var s1 = new SubSystem1(); var s2 = new SubSystem2(); this.m1 = function() { alert("вызван Facade.m1"); s1.method1(); s2.method2(); }; this.m2 = function() { alert("вызван Facade.m2"); s2.methodB(); }; } /* Client */ function Test() { var facade = new Facade(); facade.m1(); facade.m2(); } var obj = new Test(); /* Выведет: "вызван Facade.m1" "вызван SubSystem1.method1" "вызван SubSystem2.method2" "вызван Facade.m2" "вызван SubSystem2.methodB" */
CoffeeScript
Исходный текст на языке CoffeeScript# Загрузчик изображений class ImageLoader loadImage = (src) -> # ... constructor : (hash = {}) -> @images = {} @images[name] = loadImage(src) for name, src of hash # Загрузчик аудио class SoundLoader loadSound = (src) -> # ... constructor : (hash = {}) -> @sounds = {} @sounds[name] = loadSound(src) for name, src of hash # Фасад class Loader constructor : ({images, sounds}) -> @images = new ImageLoader(images).images @sounds = new SoundLoader(sounds).sounds sound : (name) -> @sounds[name] image : (name) -> @images[name]
PHP
Исходный текст на языке PHP/* Сложные части системы */ class CPU { public function freeze() { /* ... */ } public function jump( $position ) { /* ... */ } public function execute() { /* ... */ } } class Memory { public function load( $position, $data ) { /* ... */ } } class HardDrive { public function read( $lba, $size ) { /* ... */ } } /* Фасад */ class Computer { protected $cpu = null; protected $memory = null; protected $hardDrive = null; public function __construct() { $this->cpu = new CPU(); $this->memory = new Memory(); $this->hardDrive = new HardDrive(); } public function startComputer() { $this->cpu->freeze(); $this->memory->load( BOOT_ADDRESS, $this->hardDrive->read( BOOT_SECTOR, SECTOR_SIZE ) ); $this->cpu->jump( BOOT_ADDRESS ); $this->cpu->execute(); } } /* Клиентская часть */ $facade = new Computer(); $facade->startComputer();
C#
Исходный текст на языке C#using System; namespace Library { /// <summary> /// Класс подсистемы /// </summary> /// <remarks> /// <li> /// <lu>реализует функциональность подсистемы;</lu> /// <lu>выполняет работу, порученную объектом <see cref="Facade"/>;</lu> /// <lu>ничего не "знает" о существовании фасада, то есть не хранит ссылок на него;</lu> /// </li> /// </remarks> internal class SubsystemA { internal string A1() { return "Subsystem A, Method A1\n"; } internal string A2() { return "Subsystem A, Method A2\n"; } } internal class SubsystemB { internal string B1() { return "Subsystem B, Method B1\n"; } } internal class SubsystemC { internal string C1() { return "Subsystem C, Method C1\n"; } } } /// <summary> /// Facade - фасад /// </summary> /// <remarks> /// <li> /// <lu>"знает", каким классами подсистемы адресовать запрос;</lu> /// <lu>делегирует запросы клиентов подходящим объектам внутри подсистемы;</lu> /// </li> /// </remarks> public static class Facade { static Library.SubsystemA a = new Library.SubsystemA(); static Library.SubsystemB b = new Library.SubsystemB(); static Library.SubsystemC c = new Library.SubsystemC(); public static void Operation1() { Console.WriteLine("Operation 1\n" + a.A1() + a.A2() + b.B1()); } public static void Operation2() { Console.WriteLine("Operation 2\n" + b.B1() + c.C1()); } } class Program { static void Main(string[] args) { Facade.Operation1(); Facade.Operation2(); // Wait for user Console.Read(); } }
Ruby
Исходный текст на языке rubymodule Library # <summary> # Класс подсистемы # </summary> # <remarks> # <li> # <lu>реализует функциональность подсистемы;</lu> # <lu>выполняет работу, порученную объектом <see cref="Facade"/>;</lu> # <lu>ничего не "знает" о существовании фасада, то есть не хранит ссылок на него;</lu> # </li> # </remarks> class SubsystemA def a1; "Subsystem A, Method a1\n"; end def a2; "Subsystem A, Method a2\n"; end end class SubsystemB def b1; "Subsystem B, Method b1\n"; end end class SubsystemC def c1; "Subsystem C, Method c1\n"; end end end # <summary> # Facade - фасад # </summary> # <remarks> # <li> # <lu>"знает", каким классами подсистемы адресовать запрос;</lu> # <lu>делегирует запросы клиентам подходящим объектам внутри подсистемы;</lu> # </li> # </remarks> class Facade def initialize @a = Library::SubsystemA.new; @b = Library::SubsystemB.new; @c = Library::SubsystemC.new; end def operation1 puts "Operation 1\n" + @a.a1 + @a.a2 + @b.b1 end def operation2 puts "Operation 2\n" + @b.b1() + @c.c1()); end end facade = Facade.new facade.operation1 facade.operation2 # Wait for user gets
VB.NET
Исходный текст на языке VB.NETNamespace Library 'Класс подсистемы ' . реализует функциональность подсистемы ' . выполняет работу, порученную объектом Facade ' . ничего не "знает" о существовании фасада, то есть не хранит ссылок на него Friend Class SubsystemA Friend Function A1() As String Return "Subsystem A, Method A1" & vbCrLf End Function Friend Function A2() As String Return "Subsystem A, Method A2" & vbCrLf End Function End Class Friend Class SubsystemB Friend Function B1() As String Return "Subsystem B, Method B1" & vbCrLf End Function End Class Friend Class SubsystemC Friend Function C1() As String Return "Subsystem C, Method C1" & vbCrLf End Function End Class End Namespace 'Facade - фасад ' . "знает", каким классами подсистемы адресовать запрос ' . делегирует запросы клиентов подходящим объектам внутри подсистемы Public NotInheritable Class Facade Private Sub New() End Sub Shared a As New Library.SubsystemA() Shared b As New Library.SubsystemB() Shared c As New Library.SubsystemC() Public Shared Sub Operation1() Console.WriteLine("Operation 1" & vbCrLf & a.A1() & a.A2() & b.B1()) End Sub Public Shared Sub Operation2() Console.WriteLine("Operation 2" & vbCrLf & b.B1() & c.C1()) End Sub End Class Class Program Shared Sub Main() Facade.Operation1() Facade.Operation2() 'Ожидаем действия пользователя Console.Read() End Sub End Class
Delphi
Исходный текст на языке Delphiprogram FacadePattern; {$APPTYPE CONSOLE} uses SysUtils; type TComputer = class public procedure PlugIn; procedure PowerMonitor; procedure Power; end; procedure TComputer.PlugIn; begin WriteLn('Included in the network'); end; procedure TComputer.PowerMonitor; begin WriteLn('Turn on the monitor'); end; procedure TComputer.Power; begin WriteLn('Turn the system unit'); end; type TNotebook = class procedure Power; end; procedure TNotebook.Power; begin WriteLn('Press the power button'); end; type TKettle = class procedure PlugIn; procedure Power; end; procedure TKettle.Power; begin WriteLn('Press the power button'); end; procedure TKettle.PlugIn; begin WriteLn('Included in the network'); end; type TFacade = class public procedure PowerOn(aDevice: TObject); end; procedure TFacade.PowerOn(aDevice: TObject); begin if aDevice is TComputer then with TComputer(aDevice) do begin PlugIn; PowerMonitor; Power; end; if aDevice is TNotebook then with TNotebook(aDevice) do Power; if aDevice is TKettle then with TKettle(aDevice) do begin PlugIn; Power; end; WriteLn end; begin with TFacade.Create do try PowerOn(TComputer.Create); PowerOn(TNotebook.Create); PowerOn(TKettle.Create); finally Free; end; ReadLn; end.
Java
Исходный текст на языке Java/* Complex parts */ class CPU { public void freeze() { ... } public void jump(long position) { ... } public void execute() { ... } } class Memory { public void load(long position, byte[] data) { ... } } class HardDrive { public byte[] read(long lba, int size) { ... } } /* Facade */ class Computer { private CPU cpu; private Memory memory; private HardDrive hardDrive; public Computer() { this.cpu = new CPU(); this.memory = new Memory(); this.hardDrive = new HardDrive(); } public void startComputer() { cpu.freeze(); memory.load(BOOT_ADDRESS, hardDrive.read(BOOT_SECTOR, SECTOR_SIZE)); cpu.jump(BOOT_ADDRESS); cpu.execute(); } } /* Client */ class Application { public static void main(String[] args) { Computer computer = new Computer(); computer.startComputer(); } }
Литература
- Э. Гамма, Р. Хелм, Р. Джонсон, Дж. Влиссидес Приемы объектно-ориентированного проектирования. Паттерны проектирования = Design Patterns: Elements of Reusable Object-Oriented Software. — СПб: «Питер», 2007. — С. 366. — ISBN 978-5-469-01136-1 (также ISBN 5-272-00355-1)
Источники и ссылки
- Паттерн Facade (фасад) — назначение, описание, особенности и реализация на С++.
Шаблоны проектирования Основные Порождающие Структурные Адаптер • Выделение частного класса данных • Декоратор • Заместитель • Компоновщик • Мост • Приспособленец • Фасад
Поведенческие Интерпретатор • Итератор • Команда • Наблюдатель • Посетитель • Посредник • Состояние • Стратегия • Хранитель • Цепочка обязанностей • Шаблонный метод
Блокировка с двойной проверкой • Однопоточное выполнение • Планировщик Категории:- Шаблоны проектирования
- Структурные шаблоны проектирования
Wikimedia Foundation. 2010.