Я із деяких причин дуже довго думав над тим який же може бути хороший приклад для Адаптера. Можна приклад коли є операції, які так і називаються ОпераціяА та ОпА, або придумати складний приклад із кучою методів і пропертів в класі що адаптується, але весь цей час в голові у мене крутилася така штукенція, яку ми соваємо у розетку, коли разетка вузька ще СРСР-рівська а ми хочемо запхати шнур для жившення ноутбука із товстою вилкою. Майже така як на картинці збоку, але не настільки жорстока.

Отже у нас є вилка від зарядного пристрою, яка підходить в широкі роз’єми. В одній із квартир у нас усе сучасне, тому NewElectricitySystem має метод MatchWideSocket, яким ми просто можемо скористатися. В іншій квартирі у нас проблемки тому OldElectricitySytem має тільки метод MatchThinSocket. Нажаль ми не можемо собі позволити взяти дрель і роздовбати отвори в розетці – ми купляємо Адаптер, який надає можливість користуватися тою ж функціональністю споживання електричного струму, але із старої системи.

АДАПТЕР

Адаптер – це дизайн патерн, що надає можливість користуватися об’єктом, зміни у який ми не можемо робити, надаючи його функціональність через відомий нашій системі інтерфейс.

// Adaptee
class OldElectricitySystem
{
public string MatchThinSocket()
{
return "220V";
}
}
// широковикористовуваний інтерфейс
// Target
interface INewElectricitySystem
{
string MatchWideSocket();
}
class NewElectricitySystem : INewElectricitySystem
{
public string MatchWideSocket()
{
return "220V";
}
}
// Adapter
class Adapter : INewElectricitySystem
{
private readonly OldElectricitySystem _adaptee;

public Adapter(OldElectricitySystem adaptee)
{
_adaptee = adaptee;
}
// А тут коїться вся магія
// наш адаптер перекладає із того,
// що ми (код) не можемо використати наразі у те що ми можемо
public string MatchWideSocket()
{
return _adaptee.MatchThinSocket();
}
}
// Consumer
class ElectricityConsumer
{
// Зарядний пристрій розуміє тільки нову систему
public static void ChargeNotebook(INewElectricitySystem electricitySystem)
{
Console.WriteLine(electricitySystem.MatchWideSocket());
}
}

public class AdapterDemo
{
public static void Run()
{
// 1) Ми можемо і надалі користувати нашою новою системою
var newElectricitySystem = new NewElectricitySystem();
ElectricityConsumer.ChargeNotebook(newElectricitySystem);

// 2) Ми повинні адаптуватися до старої системи, використовуючи адаптер
var oldElectricitySystem = new OldElectricitySystem();
var adapter = new Adapter(oldElectricitySystem);
ElectricityConsumer.ChargeNotebook(adapter);
}
}

Ще одним ім’ям цього дизайн патерну є Wrapper із-за того що він огортає функціональність якогось об’єкту представлючи її у вигляді іншого інтерфейсу.

Насправді в реалізації не є обов’язковим композиція adaptee, наш клас Adapter міг б реалізовувати два інтерфейси – нової і старої системи. Таким чином одного разу створивши його на базі нової або старої системи, зробивши два конструктори (а чому б і ні), ми б могли використовувати його у два боки.