Паттерн Адаптер: Упрощаем Интеграцию со Сторонними Сервисами. Окончание
Начало
Пример из реальной жизни: интеграция с облачным хранилищем
Представьте себе систему, поддерживающую несколько облачных провайдеров:
- Amazon S3
- Azure Blob Storage
- Google Cloud Storage
У каждого провайдера свои SDK и API. Без адаптера код становится тесно связанным с конкретной реализацией.
1. Определение общего интерфейса
public interface ICloudStorage
{
Task UploadAsync(string container,
string file, Stream stream);
Task<Stream> DownloadAsync(
string container, string file);
Task DeleteAsync(string container,
string file);
}
Интерфейс представляет контракт вашей системы и стабильную абстракцию. Ваше приложение должно зависеть только от него.
2. Реализуем адаптер (пример для Google Cloud)
public class GoogleCloudStorageAdapter
: ICloudStorage
{
private readonly StorageClient _client;
public GoogleCloudStorageAdapter(
StorageClient client)
{
_client = client;
}
public async Task UploadAsync(
string container, string file, Stream stream)
{
await _client.UploadObjectAsync(
container, file, null, stream);
}
public async Task<Stream> DownloadAsync(
string container, string file)
{
MemoryStream stream = new();
await _client.DownloadObjectAsync(
container, file, stream);
stream.Position = 0;
return stream;
}
public async Task DeleteAsync(
string container, string file)
{
await _client.DeleteObjectAsync(container, file);
}
}
Адаптер:
- оборачивает SDK от Google,
- приводит вызовы к вашему интерфейсу,
- скрывает детали реализации.
3. Настройка внедрения зависимостей
builder.Services
.AddTransient<Func<string, ICloudStorage>>(
sp => provider =>
{
return provider switch
{
"Azure" => sp.GetRequiredService<AzureBlobStorageAdapter>(),
"Google" => sp.GetRequiredService<GoogleCloudStorageAdapter>(),
"AWS" => sp.GetRequiredService<S3StorageAdapter>(),
_ => throw new ArgumentException("Неподдерживаемый провайдер")
};
});
Пояснение
- адаптер выбирается динамически,
- обеспечивается гибкость системы,
- есть возможность переключаться во время выполнения.
Когда использовать Адаптер
- интеграция сторонних API,
- работа с устаревшими системами,
- стандартизация нескольких провайдеров,
- переключение реализаций.
Когда не использовать
- интерфейсы уже совместимы,
- преобразование тривиально,
- производительность крайне важна,
- абстракция добавляет ненужную сложность.
Источник: https://thecodeman.net/posts/simplifying-integration-with-adapter-pattern