Мост (шаблон проектирования)
Материал из Seo Wiki - Поисковая Оптимизация и Программирование
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); }; }
| структурные шаблоны проектирования |
|
адаптер | мост | компоновщик | декоратор | фасад | заместитель | приспособленец | Выделение частного класса данных |
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:橋接模式