Мост (шаблон проектирования)
Bridge, Мост — шаблон проектирования, используемый в проектировании программного обеспечения чтобы «разделять абстракцию и реализацию так, чтобы они могли изменяться независимо». Шаблон bridge (от англ. — мост) использует инкапсуляцию, агрегирование и может использовать наследование для того, чтобы разделить ответственность между классами.
Цель
При частом изменении класса, преимущества объектно-ориентированного подхода становятся очень полезными, позволяя делать изменения в программе, обладая минимальными сведениями о реализации программы. Шаблон bridge является полезным там, где не только сам класс часто меняется, но и то, что класс делает.
Описание
Когда абстракция и реализация разделены, они могут изменяться независимо. Рассмотрим такую абстракцию как фигура. Существует множество типов фигур, каждая со своими свойствами и методами. Однако есть что-то, что объединяет все фигуры. Например, каждая фигура должна уметь рисовать себя, масштабироваться и т. п. В то же время рисование графики может отличаться в зависимости от типа ОС, или графической библиотеки. Фигуры должны иметь возможность рисовать себя в различных графических средах, но реализовывать в каждой фигуре все способы рисования или модифицировать фигуру каждый раз при изменении способа рисования непрактично. В этом случае помогает шаблон bridge, позволяя создавать новые классы, которые будут реализовывать рисование в различных графических средах. При использовании такого подхода очень легко можно добавлять как новые фигуры, так и способы их рисования.
Примеры
Пример на C#
using System;
namespace Bridge
{
// MainApp test application
class MainApp
{
static void Main()
{
Abstraction ab = new RefinedAbstraction();
// Set implementation and call
ab.Implementor = new ConcreteImplementorA();
ab.Operation();
// Change implemention and call
ab.Implementor = new ConcreteImplementorB();
ab.Operation();
// Wait for user
Console.Read();
}
}
/// <summary>
/// Abstraction - абстракция
/// </summary>
/// <remarks>
/// <li>
/// <lu>определяем интерфейс абстракции;</lu>
/// <lu>хранит ссылку на объект <see cref="Implementor"/></lu>
/// </li>
/// </remarks>
class Abstraction
{
protected Implementor implementor;
// Property
public Implementor Implementor
{
set{ implementor = value; }
}
public virtual void Operation()
{
implementor.Operation();
}
}
/// <summary>
/// Implementor - реализатор
/// </summary>
/// <remarks>
/// <li>
/// <lu>определяет интерфейс для классов реализации. Он не обязан точно
/// соотведствовать интерфейсу класса <see cref="Abstraction"/>. На самом деле оба
/// интерфейса могут быть совершенно различны. Обычно интерфейс класса
/// <see cref="Implementor"/> представляет только примитивные операции, а класс
/// <see cref="Abstraction"/> определяет операции более высокого уровня,
/// базирующиеся на этих примитивах;</lu>
/// </li>
/// </remarks>
abstract class Implementor
{
public abstract void Operation();
}
/// <summary>
/// RefinedAbstraction - уточненная абстракция
/// </summary>
/// <remarks>
/// <li>
/// <lu>расширяет интерфейс, определенный абстракцией <see cref="Abstraction"/></lu>
/// </li>
/// </remarks>
class RefinedAbstraction : Abstraction
{
public override void Operation()
{
implementor.Operation();
}
}
/// <summary>
/// ConcreteImplementor - конкретный реализатор
/// </summary>
/// <remarks>
/// <li>
/// <lu>содержит конкретную реализацию интерфейса <see cref="Implementor"/></lu>
/// </li>
/// </remarks>
class ConcreteImplementorA : Implementor
{
public override void Operation()
{
Console.WriteLine("ConcreteImplementorA Operation");
}
}
// "ConcreteImplementorB"
class ConcreteImplementorB : Implementor
{
public override void Operation()
{
Console.WriteLine("ConcreteImplementorB Operation");
}
}
}
Пример JavaScript
// Implementor ("интерфейс")
function Implementor() {
this.operation = function() {};
}
// ConcreteImplementor (реализация Implementor)
function ConcreteImplementorA() {
this.operation = function() {
alert("ConcreteImplementorA.operation");
};
}
ConcreteImplementorA.prototype = new Implementor();
ConcreteImplementorA.prototype.constructor = ConcreteImplementorA;
function ConcreteImplementorB() {
this.operation = function() {
alert("ConcreteImplementorB.operation");
};
}
ConcreteImplementorB.prototype = new Implementor();
ConcreteImplementorB.prototype.constructor = ConcreteImplementorB;
// Abstraction
function Abstraction() {
var implementor;
this.getImplementor = function() {
// доступ к implementor'у из RefinedAbstraction
return implementor;
};
this.setImplementor = function(val) {
implementor = val;
};
this.operation = function() {
implementor.operation();
};
}
// RefinedAbstraction
function RefinedAbstraction() {
var abstr = new Abstraction();
this.setImplementor = function(val) {
abstr.setImplementor(val);
};
this.operation = function() {
abstr.operation();
};
}
// использование:
var refAbstr = new RefinedAbstraction();
refAbstr.setImplementor( new ConcreteImplementorA() );
refAbstr.operation(); // "ConcreteImplementorA.operation"
refAbstr.setImplementor( new ConcreteImplementorB() );
refAbstr.operation(); // "ConcreteImplementorB.operation"
Без необходимости перегрузки методов Abstraction, можно значительно упростить RefinedAbstraction:
function RefinedAbstraction() {
Abstraction.call(this);
}
Так же можно сохранить ссылки на перегружаемые методы сразу после инстанцирования Abstraction:
function RefinedAbstraction() {
Abstraction.call(this);
var abstr_setImplementor = this.setImplementor;
this.setImplementor = function(val) {
abstr_setImplementor(val);
};
}
структурные шаблоны проектирования |
адаптер | мост | компоновщик | декоратор | фасад | заместитель | приспособленец | Выделение частного класса данных |
bg:Мост (шаблон) de:Brücke (Entwurfsmuster) en:Bridge pattern es:Bridge (patrón de diseño) fr:Pont (patron de conception) it:Bridge pattern ja:Bridge パターン ko:브리지 패턴 pl:Most (wzorzec projektowy) pt:Bridge (padrão) uk:Міст (шаблон проектування) vi:Bridge pattern zh:橋接模式
Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....