Ответ
Адаптер (Adapter) — это структурный паттерн проектирования, который позволяет объектам с несовместимыми интерфейсами работать вместе. Он выступает в роли «переводчика» или «прослойки», преобразуя интерфейс одного класса в интерфейс, ожидаемый клиентом.
Аналогия из жизни: Это переходник для розетки, который позволяет вилке одного стандарта работать с розеткой другого.
Когда использовать:
- Когда нужно использовать существующий класс, но его интерфейс не соответствует требованиям вашего кода.
- Для интеграции сторонних библиотек или legacy-кода без изменения их исходного кода.
- Когда нужно создать унифицированный интерфейс для нескольких классов с разными интерфейсами.
Реализация: Существует два основных типа адаптеров:
1. Адаптер на основе композиции (объектный адаптер) — предпочтительный способ.
// Целевой интерфейс, который ожидает клиентский код
public interface ITarget
{
string GetRequest();
}
// Адаптируемый класс с «чужим» интерфейсом
public class Adaptee
{
public string GetSpecificRequest()
{
return "Specific request from Adaptee.";
}
}
// Адаптер: реализует целевой интерфейс и содержит ссылку на Adaptee
public class Adapter : ITarget
{
private readonly Adaptee _adaptee;
public Adapter(Adaptee adaptee)
{
_adaptee = adaptee;
}
public string GetRequest()
{
// Преобразование вызова GetRequest() в вызов GetSpecificRequest()
return _adaptee.GetSpecificRequest();
}
}
// Клиентский код работает только с интерфейсом ITarget
class Client
{
static void Main()
{
Adaptee adaptee = new Adaptee();
ITarget target = new Adapter(adaptee); // Обёртывание
Console.WriteLine(target.GetRequest()); // Вывод: Specific request from Adaptee.
}
}
2. Адаптер на основе наследования (классовый адаптер) — требует множественного наследования (недоступно в C#, но возможно в C++).
Преимущества:
- Принцип единой ответственности: Отделяет код преобразования интерфейса от основной бизнес-логики.
- Принцип открытости/закрытости: Позволяет вводить новые адаптеры, не ломая существующий клиентский код.
- Повторное использование: Делает несовместимые классы пригодными для использования.
Недостатки:
- Усложняет код, добавляя новые классы. Иногда проще изменить клиентский код, если это возможно.