В чем разница между шаблонами "Мост" и "Адаптер"?
В чем разница между шаблонами "Мост" и "Адаптер"?
Ответы:
«Адаптер заставляет вещи работать после того, как они спроектированы; Bridge заставляет их работать раньше, чем они есть. [GoF, p219]»
Фактически, шаблон адаптера полезен, когда у вас есть существующий код, будь то сторонний или собственный, но который находится вне вашего контроля или не может быть изменен иным образом, чтобы полностью соответствовать интерфейсу, который вам нужен. Например, у нас есть SuperWeaponsArray, который может управлять множеством устройств судного дня.
public class SuperWeaponsArray {
/*...*/
public void destroyWorld() {
for (Weapon w : armedWeapons) {
w.fire();
}
}
}
Отлично. За исключением того, что мы понимаем, что в нашем арсенале есть ядерное устройство, которое задолго до перехода на интерфейс оружия. Но нам бы очень хотелось, чтобы это работало здесь ... так что же нам делать ... вклинить его!
NukeWeaponsAdaptor - основан на нашем классе Nuke, но экспортирует интерфейс оружия. Милая, теперь мы, несомненно, можем уничтожить мир. Это похоже на кладж, но он заставляет все работать.
мостШаблон - это то, что вы реализуете заранее - если вы знаете, что у вас есть две ортогональные иерархии, он предоставляет способ разделить интерфейс и реализацию таким образом, чтобы вы не получили безумное количество классов. Допустим, у вас есть:
Типы файловых объектов MemoryMappedFile и DirectReadFile. Допустим, вы хотите иметь возможность читать файлы из различных источников (возможно, Linux или Windows и т. Д.). Bridge поможет вам избежать:
MemoryMappedWindowsFile MemoryMappedLinuxFile DirectReadWindowsFile DirectReadLinuxFile
http://en.wikipedia.org/wiki/Adapter_pattern
Шаблон адаптера больше предназначен для того, чтобы ваш существующий код работал с новой системой или интерфейсом.
Если у вас есть набор стандартных API веб-служб, которые вы хотели бы предложить для существующего интерфейса расширяемости другого приложения, вы можете подумать о написании набора адаптеров для этого. Обратите внимание, что есть серая область, и это больше касается того, как вы технически определяете шаблон, поскольку другие шаблоны, такие как фасад, аналогичны.
http://en.wikipedia.org/wiki/Bridge_pattern
Шаблон «Мост» позволит вам, возможно, иметь альтернативные реализации алгоритма или системы.
Хотя это и не классический пример паттерна моста, представьте, что у вас есть несколько реализаций хранилища данных: одна эффективна в пространстве, другая эффективна в сырой производительности ... и у вас есть экономическое обоснование для предложения как в вашем приложении, так и в среде ,
Что касается вашего вопроса, «где я могу использовать какой шаблон», ответ будет везде, где это имеет смысл для вашего проекта! Возможно, подумайте о том, чтобы предложить уточняющую правку, чтобы направить дискуссию на то, где, по вашему мнению, вам нужно использовать то или другое.
адаптер:
Диаграмма UML: из внутренней статьи:
Target : определяет интерфейс для домена, который использует Клиент.
Адаптер : адаптирует интерфейс адаптируемого к целевому интерфейсу.
Адаптация : определяет существующий интерфейс, который необходимо адаптировать.
Клиент : взаимодействует с объектами, соответствующими интерфейсу Target.
Пример:
Квадрат и Прямоугольник - это две разные формы, и получение area () каждой из них требует разных методов. Но все же Square работает над интерфейсом Rectangle с преобразованием некоторых свойств.
public class AdapterDemo{
public static void main(String args[]){
SquareArea s = new SquareArea(4);
System.out.println("Square area :"+s.getArea());
}
}
class RectangleArea {
public int getArea(int length, int width){
return length * width;
}
}
class SquareArea extends RectangleArea {
int length;
public SquareArea(int length){
this.length = length;
}
public int getArea(){
return getArea(length,length);
}
}
мост:
РЕДАКТИРОВАТЬ: (согласно предложению @quasoft)
У вас есть четыре компонента в этом шаблоне.
Абстракция : определяет интерфейс
RefinedAbstraction : реализует абстракцию:
Разработчик : определяет интерфейс для реализации.
ConcreteImplementor : он реализует интерфейс разработчика.
Фрагмент кода:
Gear gear = new ManualGear();
Vehicle vehicle = new Car(gear);
vehicle.addGear();
gear = new AutoGear();
vehicle = new Car(gear);
vehicle.addGear();
Связанный пост:
Когда вы используете паттерн мост? Чем он отличается от шаблона адаптера?
Ключевые отличия: из исходной статьи
Этот пост существует довольно давно. Однако важно понимать, что фасад чем-то похож на адаптер, но это не совсем то же самое. Адаптер «адаптирует» существующий класс к обычно несовместимому клиентскому классу. Допустим, у вас есть старая система рабочих процессов, которую ваше приложение использует в качестве клиента. Возможно, ваша компания заменит систему документооборота на новую «несовместимую» (с точки зрения интерфейсов). В большинстве случаев вы можете использовать шаблон адаптера и написать код, который фактически вызывает интерфейсы нового механизма рабочего процесса. Мост обычно используется иначе. Если у вас действительно есть система, которая должна работать с разными файловыми системами (например, локальный диск, NFS и т. Д.), Вы можете использовать шаблон моста и создать один уровень абстракции для работы со всеми вашими файловыми системами. По сути, это был бы простой вариант использования шаблона моста. Фасад и адаптер имеют общие свойства, нофасады обычно используются для упрощения существующего интерфейса / класса . В первые дни EJB не было местных вызовов для EJB. Разработчики всегда получали заглушку, сужали ее и называли «псевдо-удаленно». Это часто приводило к проблемам с производительностью (особенно при вызове по сети). Опытные разработчики могли бы использовать паттерн фасада, чтобы предоставить клиенту очень крупнозернистый интерфейс. Этот фасад, в свою очередь, будет выполнять несколько вызовов различных более тонких методов. В целом это значительно сократило количество требуемых вызовов методов и повысило производительность.
Мост улучшен Адаптер. Bridge включает адаптер и добавляет ему дополнительную гибкость. Вот как элементы из карты ответов Равиндры между шаблонами:
Adapter | Bridge
-----------|---------------
Target | Abstraction
-----------|---------------
| RefinedAbstraction
|
| This element is Bridge specific. If there is a group of
| implementations that share the same logic, the logic can be placed here.
| For example, all cars split into two large groups: manual and auto.
| So, there will be two RefinedAbstraction classes.
-----------|---------------
Adapter | Implementor
-----------|---------------
Adaptee | ConcreteImplementor
В верхнем ответе @James цитирует предложение из GoF, стр. 219. Я думаю, что стоит воспроизвести здесь полное объяснение.
Адаптер против моста
У шаблонов адаптера и моста есть несколько общих атрибутов. Оба способствуют гибкости, обеспечивая уровень косвенного обращения к другому объекту. Оба включают пересылку запросов к этому объекту из интерфейса, отличного от его собственного.
Ключевое различие между этими шаблонами заключается в их назначении. Адаптер фокусируется на устранении несовместимости между двумя существующими интерфейсами. Он не фокусируется на том, как реализованы эти интерфейсы, и не рассматривает, как они могут развиваться независимо. Это способ заставить два независимо разработанных класса работать вместе, не переопределяя один или другой. Bridge, с другой стороны, соединяет абстракцию и ее (потенциально многочисленные) реализации. Он обеспечивает стабильный интерфейс для клиентов, даже если позволяет вам изменять классы, которые его реализуют. Он также включает новые реализации по мере развития системы.
В результате этих различий адаптер и мост часто используются на разных этапах жизненного цикла программного обеспечения. Адаптер часто становится необходимым, когда вы обнаруживаете, что два несовместимых класса должны работать вместе, как правило, чтобы избежать репликации кода. Муфта непредвиденная. Напротив, пользователь моста заранее понимает, что абстракция должна иметь несколько реализаций, и обе могут развиваться независимо. Шаблон адаптера заставляет вещи работать после того, как они спроектированы; Мост заставляет их работать раньше, чем они есть. Это не значит, что Adapter чем-то уступает Bridge; каждый шаблон просто обращается к другой проблеме.
Предположим, у вас есть абстрактный класс Shape с (общей / абстрактной) функцией рисования и Circle, который реализует Shape. Шаблон моста - это просто двухсторонний абстракционный подход, позволяющий разделить реализацию (рисование в круге) и общие / абстрактные функции (рисование в классе Shape).
Что это на самом деле значит? На первый взгляд, это похоже на то, что вы уже делаете (путем инверсии зависимостей). Так что не беспокойтесь о менее сложном или более модульном коде. Но за этим стоит более глубокая философия.
Насколько я понимаю, необходимость в шаблоне использования может возникнуть, когда мне нужно добавить новые классы, которые тесно связаны с текущей системой (например, RedCircle или GreenCircle) и которые отличаются только одной функциональностью (например, цветом). И мне понадобится шаблон Bridge, особенно если существующие системные классы (Circle или Shape) должны часто изменяться, и вы не хотите, чтобы эти изменения влияли на вновь добавленные классы. Вот почему общие функции рисования абстрагируются в новом интерфейсе, чтобы вы могли изменять поведение рисования независимо от формы или круга.