Adapter

По своей сути паттерн Адаптер очень прост. Его реализация заключается в создании обёртки над объектом, имплементирующей нужный интерфейс. Имлементация методов интерфейса, соответсвенно, должна выглядеть как преобразование аргументов и вызов методов у оборачиваемого объекта.

Target - целевой интерфейс, который имплементирует класс обёртка

Adaptee - оборачиваемый объект

Adapter - объект-обёртка

Паттерн Адаптер можно использовать как посредника для достижения полиморфизма между типами не находящимися в одной иерархии. Он является склейкой между объектами имеющими различные интерфейсы.

Применение адаптера может быть полезно в ситуациях когда код объединяемых типов не может быть изменён, либо когда его изменения несут за собой сильные риски.

public class SqlServerLogSaver
{
		public void Save(string message, DateTime timeStamp, int severity) { ... }
}

public class ElasticLogSaver
{
		public void Save(ElasticLogMessage message);
}

public interface ILogSaver
{
		void Save(LogEntry entry);
}

public SqlServerLogSaverAdapter : ILogSaver
{
		private readonly SqlServerLogSaver _saver;

		public void Save(LogEntry entry)
		{
				_saver.Save(entry.Message, entry.DateTime, entry.Severity.AsInteger());
		}
}

public ElasticLogSaverAdapter : ILogSaver
{
		private readonly ElasticLogSaver _saver;

		public void Save(LogEntry entry)
		{
				_saver.Save(entry.AsElasticLogMessage());
		}
}

Адаптивный рефакторинг

Паттерн адаптер может быть использован для локализации рефакторинга. Предположим вы проводите рефакторинг кода, который требует изменение интерфейса используемых объектов (добавление асинхронности в нашу систему логирования). На первый взгляд, это приведёт к тому, что придётся изменять как код, использующий старые интерфейсы (на использование новых), так и код, реализующий старые интерфейсы (на реализацию новых).

Изменения можно локализовать путём добавления адаптера, из старого интерфейса в новый, соответсвенно рефакторинг можно разбить на два шага, изменение использований, изменение реализаций, после которых добавленные адаптеры можно будет удалить за ненадобностью.

public IAsyncLogSaver
{
		Task SaveAsync(SaveAsync entry);
}

public AsyncLogSaverAdapter : IAsyncLogSaver
{
		private readonly ILogSaver _saver;

		public Task SaveAsync(SaveAsync entry)
		{
				_saver.Save(entry);
				return Task.CompletedTask;
		}
}