
Мост на C#
Мост — это структурный паттерн, который разделяет бизнес-логику или большой класс на несколько отдельных иерархий, которые потом можно развивать отдельно друг от друга.
Одна из этих иерархий (абстракция) получит ссылку на объекты другой иерархии (реализация) и будет делегировать им основную работу. Благодаря тому, что все реализации будут следовать общему интерфейсу, их можно будет взаимозаменять внутри абстракции.
Сложность:
Популярность:
Применимость: Паттерн Мост особенно полезен когда вам приходится делать кросс-платформенные приложения, поддерживать несколько типов баз данных или работать с разными поставщиками похожего API (например, cloud-сервисы, социальные сети и т. д.)
Признаки применения паттерна: Если в программе чётко выделены классы «управления» и несколько видов классов «платформ», причём управляющие объекты делегируют выполнение платформам, то можно сказать, что у вас используется Мост.
Концептуальный пример
Этот пример показывает структуру паттерна Мост, а именно — из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.
Program.cs: Пример структуры паттерна
using System;
namespace RefactoringGuru.DesignPatterns.Bridge.Conceptual
{
// Абстракция устанавливает интерфейс для «управляющей» части двух иерархий
// классов. Она содержит ссылку на объект из иерархии Реализации и
// делегирует ему всю настоящую работу.
class Abstraction
{
protected IImplementation _implementation;
public Abstraction(IImplementation implementation)
{
this._implementation = implementation;
}
public virtual string Operation()
{
return "Abstract: Base operation with:\n" +
_implementation.OperationImplementation();
}
}
// Можно расширить Абстракцию без изменения классов Реализации.
class ExtendedAbstraction : Abstraction
{
public ExtendedAbstraction(IImplementation implementation) : base(implementation)
{
}
public override string Operation()
{
return "ExtendedAbstraction: Extended operation with:\n" +
base._implementation.OperationImplementation();
}
}
// Реализация устанавливает интерфейс для всех классов реализации. Он не
// должен соответствовать интерфейсу Абстракции. На практике оба интерфейса
// могут быть совершенно разными. Как правило, интерфейс Реализации
// предоставляет только примитивные операции, в то время как Абстракция
// определяет операции более высокого уровня, основанные на этих примитивах.
public interface IImplementation
{
string OperationImplementation();
}
// Каждая Конкретная Реализация соответствует определённой платформе и
// реализует интерфейс Реализации с использованием API этой платформы.
class ConcreteImplementationA : IImplementation
{
public string OperationImplementation()
{
return "ConcreteImplementationA: The result in platform A.\n";
}
}
class ConcreteImplementationB : IImplementation
{
public string OperationImplementation()
{
return "ConcreteImplementationB: The result in platform B.\n";
}
}
class Client
{
// За исключением этапа инициализации, когда объект Абстракции
// связывается с определённым объектом Реализации, клиентский код должен
// зависеть только от класса Абстракции. Таким образом, клиентский код
// может поддерживать любую комбинацию абстракции и реализации.
public void ClientCode(Abstraction abstraction)
{
Console.Write(abstraction.Operation());
}
}
class Program
{
static void Main(string[] args)
{
Client client = new Client();
Abstraction abstraction;
// Клиентский код должен работать с любой предварительно
// сконфигурированной комбинацией абстракции и реализации.
abstraction = new Abstraction(new ConcreteImplementationA());
client.ClientCode(abstraction);
Console.WriteLine();
abstraction = new ExtendedAbstraction(new ConcreteImplementationB());
client.ClientCode(abstraction);
}
}
}
Output.txt: Результат выполнения
Abstract: Base operation with:
ConcreteImplementationA: The result in platform A.
ExtendedAbstraction: Extended operation with:
ConcreteImplementationA: The result in platform B.