Фасад (шаблон проектирования) | это... Что такое Фасад (шаблон проектирования)? (original) (raw)

У этого термина существуют и другие значения, см. Фасад (значения).

Шаблон проектирования

Фасад
Facade
Тип: структурный
Описан в Design Patterns Да

Шаблон Facade (Фасад)Шаблон проектирования, позволяющий скрыть сложность системы путем сведения всех возможных внешних вызовов к одному объекту, делегирующему их соответствующим объектам системы.

Содержание

Описание

Facade.gif

Проблема

Как обеспечить унифицированный интерфейс с набором разрозненных реализаций или интерфейсов, например, с подсистемой, если нежелательно высокое связывание с этой подсистемой или реализация подсистемы может измениться?

Решение

Определить одну точку взаимодействия с подсистемой — фасадный объект, обеспечивающий общий интерфейс с подсистемой и возложить на него обязанность по взаимодействию с её компонентами. Фасад — это внешний объект, обеспечивающий единственную точку входа для служб подсистемы. Реализация других компонентов подсистемы закрыта и не видна внешним компонентам. Фасадный объект обеспечивает реализацию паттерна Устойчивый к изменениям (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>&gt;</mo><mi>m</mi><mi>e</mi><mi>m</mi><mi>o</mi><mi>r</mi><mi>y</mi><mo>−</mo><mo>&gt;</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-&gt;memory-&gt;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">&gt;</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">&gt;</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 { ///

/// Класс подсистемы /// /// ///
  • /// реализует функциональность подсистемы; /// выполняет работу, порученную объектом ; /// ничего не "знает" о существовании фасада, то есть не хранит ссылок на него; ///
  • /// 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"; } } }

    ///

    /// Facade - фасад /// /// ///
  • /// "знает", каким классами подсистемы адресовать запрос; /// делегирует запросы клиентов подходящим объектам внутри подсистемы; ///
  • /// 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

    Исходный текст на языке 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(); } }

    Литература

    Источники и ссылки

    Просмотр этого шаблона Шаблоны проектирования
    Основные ДелегированияИнтерфейсНеизменяемый объектФункционального дизайна
    Порождающие Абстрактная фабрикаОбъектный пулОдиночкаОтложенная инициализацияПрототипСтроительФабричный метод
    Структурные АдаптерВыделение частного класса данныхДекораторЗаместительКомпоновщикМостПриспособленецФасад
    Поведенческие ИнтерпретаторИтераторКомандаНаблюдательПосетительПосредникСостояниеСтратегияХранительЦепочка обязанностейШаблонный метод
    Блокировка с двойной проверкой • Однопоточное выполнениеПланировщик