Фасад (шаблон проектирования) | это... Что такое Фасад (шаблон проектирования)? (original) (raw)
У этого термина существуют и другие значения, см. Фасад (значения).
Шаблон проектирования
Фасад | |
---|---|
Facade | |
Тип: | структурный |
Описан в Design Patterns | Да |
Шаблон Facade (Фасад) — Шаблон проектирования, позволяющий скрыть сложность системы путем сведения всех возможных внешних вызовов к одному объекту, делегирующему их соответствующим объектам системы.
Содержание
Описание
Проблема
Как обеспечить унифицированный интерфейс с набором разрозненных реализаций или интерфейсов, например, с подсистемой, если нежелательно высокое связывание с этой подсистемой или реализация подсистемы может измениться?
Решение
Определить одну точку взаимодействия с подсистемой — фасадный объект, обеспечивающий общий интерфейс с подсистемой и возложить на него обязанность по взаимодействию с её компонентами. Фасад — это внешний объект, обеспечивающий единственную точку входа для служб подсистемы. Реализация других компонентов подсистемы закрыта и не видна внешним компонентам. Фасадный объект обеспечивает реализацию паттерна Устойчивый к изменениям (Protected Variations) с точки зрения защиты от изменений в реализации подсистемы.
Особенности применения
Шаблон применяется для установки некоторого рода политики по отношению к другой группе объектов. Если политика должна быть яркой и заметной, следует воспользоваться услугами шаблона Фасад. Если же необходимо обеспечить скрытность и аккуратность (прозрачность), более подходящим выбором является шаблон Заместитель (Proxy).
Примеры
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
Загрузчик изображений
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,position, position,data ) { /* ... */ } }
class HardDrive { public function read( lba,lba, 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();
<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>t</mi><mi>h</mi><mi>i</mi><mi>s</mi><mo>−</mo><mo>></mo><mi>m</mi><mi>e</mi><mi>m</mi><mi>o</mi><mi>r</mi><mi>y</mi><mo>−</mo><mo>></mo><mi>l</mi><mi>o</mi><mi>a</mi><mi>d</mi><mo stretchy="false">(</mo><mi>B</mi><mi>O</mi><mi>O</mi><msub><mi>T</mi><mi>A</mi></msub><mi>D</mi><mi>D</mi><mi>R</mi><mi>E</mi><mi>S</mi><mi>S</mi><mo separator="true">,</mo></mrow><annotation encoding="application/x-tex">this->memory->load( BOOT_ADDRESS, </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">t</span><span class="mord mathnormal">hi</span><span class="mord mathnormal">s</span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">m</span><span class="mord mathnormal">e</span><span class="mord mathnormal">m</span><span class="mord mathnormal" style="margin-right:0.03588em;">ory</span><span class="mord">−</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">o</span><span class="mord mathnormal">a</span><span class="mord mathnormal">d</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">BOO</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">A</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.02778em;">DD</span><span class="mord mathnormal" style="margin-right:0.05764em;">RESS</span><span class="mpunct">,</span></span></span></span>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
{
///
///
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
Исходный текст на языке ruby
module 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
Facade - фасад
"знает", каким классами подсистемы адресовать запрос;
делегирует запросы клиентам подходящим объектам внутри подсистемы;
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.NET
Namespace 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
Исходный текст на языке Delphi
program 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 (фасад) — назначение, описание, особенности и реализация на С++.
Шаблоны проектирования | |
---|---|
Основные | Делегирования • Интерфейс • Неизменяемый объект • Функционального дизайна |
Порождающие | Абстрактная фабрика • Объектный пул • Одиночка • Отложенная инициализация • Прототип • Строитель • Фабричный метод |
Структурные | Адаптер • Выделение частного класса данных • Декоратор • Заместитель • Компоновщик • Мост • Приспособленец • Фасад |
Поведенческие | Интерпретатор • Итератор • Команда • Наблюдатель • Посетитель • Посредник • Состояние • Стратегия • Хранитель • Цепочка обязанностей • Шаблонный метод |
Блокировка с двойной проверкой • Однопоточное выполнение • Планировщик |