Adapter Design pattern -swift- Examples
The Adapter design pattern is a design pattern that allows two incompatible interfaces to work together by creating a third object that acts as a translator between them.
For example, imagine that you have an application that expects data in JSON format, but you need to integrate it with a legacy system that only provides data in XML format. Instead of modifying the application to accept XML, you could create an adapter class that translates between JSON and XML, allowing the two systems to communicate seamlessly.
Improved reusability: Adapters can be used to make existing classes or APIs work together without modifying their code. This makes it easier to reuse existing components and APIs in new contexts.
Reduced complexity: Adapters can simplify code by providing a standard interface for interacting with multiple classes or APIs. This reduces the complexity of the code needed to work with those components and improves maintainability.
Increased flexibility: Adapters can provide a layer of abstraction that allows components to be easily swapped out or replaced with minimal changes to the overall system. This can make it easier to evolve a system over time as requirements change.
Facilitates integration: Adapters can be used to integrate new components or APIs into existing systems that were not originally designed to work together. This makes it easier to add new features and functionality to existing systems without requiring major modifications to the underlying code.
Here are different examples to learn Adapter Design Pattern:-
protocol AudioPlayer {
func play()
}
class ThirdPartyAudioPlayer {
func playAudio() {
print("Playing audio with ThirdPartyAudioPlayer")
}
}
class ThirdPartyAudioPlayerAdapter: AudioPlayer {
private let thirdPartyPlayer: ThirdPartyAudioPlayer
init(thirdPartyPlayer: ThirdPartyAudioPlayer) {
self.thirdPartyPlayer = thirdPartyPlayer
}
func play() {
thirdPartyPlayer.playAudio()
}
}
let thirdPartyPlayer = ThirdPartyAudioPlayer()
let adapter = ThirdPartyAudioPlayerAdapter(thirdPartyPlayer: thirdPartyPlayer)
adapter.play() // Output: "Playing audio with ThirdPartyAudioPlayer"
protocol PaymentProvider {
func processPayment(amount: Double, token: String)
}
class ThirdPartyPaymentGateway {
func submitPayment(amount: Double, token: String) {
print("Processing payment with ThirdPartyPaymentGateway")
}
}
class ThirdPartyPaymentGatewayAdapter: PaymentProvider {
private let thirdPartyGateway: ThirdPartyPaymentGateway
init(thirdPartyGateway: ThirdPartyPaymentGateway) {
self.thirdPartyGateway = thirdPartyGateway
}
func processPayment(amount: Double, token: String) {
thirdPartyGateway.submitPayment(amount: amount, token: token)
}
}
let thirdPartyGateway = ThirdPartyPaymentGateway()
let adapter = ThirdPartyPaymentGatewayAdapter(thirdPartyGateway: thirdPartyGateway)
adapter.processPayment(amount: 100.0, token: "abc123") // Output: "Processing payment with ThirdPartyPaymentGateway"
protocol URLShortener {
func shortenURL(url: String) -> String
}
class ThirdPartyURLShortener {
func shorten(url: String) -> String {
print("Shortening URL with ThirdPartyURLShortener")
return "https://short.ly/1234"
}
}
class ThirdPartyURLShortenerAdapter: URLShortener {
private let thirdPartyShortener: ThirdPartyURLShortener
init(thirdPartyShortener: ThirdPartyURLShortener) {
self.thirdPartyShortener = thirdPartyShortener
}
func shortenURL(url: String) -> String {
return thirdPartyShortener.shorten(url: url)
}
}
let thirdPartyShortener = ThirdPartyURLShortener()
let adapter = ThirdPartyURLShortenerAdapter(thirdPartyShortener: thirdPartyShortener)
let shortURL = adapter.shortenURL(url: "https://example.com/long-url")
print(shortURL) // Output: "https://short.ly/1234"
protocol NewsProvider {
func getArticles(completion: @escaping ([Article]) -> Void)
}
class ThirdPartyNewsAPI {
func fetchNews(success: @escaping ([String: Any]) -> Void, failure: @escaping (Error) -> Void) {
print("Fetching news with ThirdPartyNewsAPI")
let response: [String: Any] = [
"articles": [
["title": "Article 1", "description": "Article 1 description"],
["title": "Article 2", "description": "Article 2 description"]
]
]
success(response)
}
}
class ThirdPartyNewsAPIAdapter: NewsProvider {
private let thirdPartyNewsAPI: ThirdPartyNewsAPI
init(thirdPartyNewsAPI: ThirdPartyNewsAPI) {
self.thirdPartyNewsAPI = thirdPartyNewsAPI
}
func getArticles(completion: @escaping ([Article]) -> Void) {
thirdPartyNewsAPI.fetchNews(success: { response in
let articles = response["articles"] as? [[String: Any]] ?? []
let mappedArticles = articles.map { article in
Article(title: article["title"] as? String ?? "",
description: article["description"] as? String ?? "")
}
completion(mappedArticles)
}, failure: { error in
print("Error fetching news: \(error.localizedDescription)")
completion([])
})
}
}
struct Article {
let title: String
let description: String
}
let thirdPartyNewsAPI = ThirdPartyNewsAPI()
let adapter = ThirdPartyNewsAPIAdapter(thirdPartyNewsAPI: thirdPartyNewsAPI)
adapter.getArticles(completion: { articles in
print(articles)
})
protocol WeatherProvider {
func getCurrentWeather(city: String, completion: @escaping (WeatherData?) -> Void)
}
class ThirdPartyWeatherAPI {
func fetchWeather(for city: String, success: @escaping ([String: Any]) -> Void, failure: @escaping (Error) -> Void) {
print("Fetching weather data with ThirdPartyWeatherAPI")
let response: [String: Any] = [
"weather": [
["description": "Clear sky"],
],
"main": [
"temp": 23.5
]
]
success(response)
}
}
class ThirdPartyWeatherAPIAdapter: WeatherProvider {
private let thirdPartyWeatherAPI: ThirdPartyWeatherAPI
init(thirdPartyWeatherAPI: ThirdPartyWeatherAPI) {
self.thirdPartyWeatherAPI = thirdPartyWeatherAPI
}
func getCurrentWeather(city: String, completion: @escaping (WeatherData?) -> Void) {
thirdPartyWeatherAPI.fetchWeather(for: city, success: { response in
let weatherDescriptions = response["weather"] as? [[String: Any]] ?? []
let mainInfo = response["main"] as? [String: Any] ?? [:]
let temperature = mainInfo["temp"] as? Double ?? 0.0
if let firstWeatherDescription = weatherDescriptions.first,
let weatherDescription = firstWeatherDescription["description"] as? String {
let weatherData = WeatherData(city: city, weatherDescription: weatherDescription, temperature: temperature)
completion(weatherData)
} else {
completion(nil)
}
}, failure: { error in
print("Error fetching weather data: \(error.localizedDescription)")
completion(nil)
})
}
}
struct WeatherData {
let city: String
let weatherDescription: String
let temperature: Double
}
let thirdPartyWeatherAPI = ThirdPartyWeatherAPI()
let adapter = ThirdPartyWeatherAPIAdapter(thirdPartyWeatherAPI: thirdPartyWeatherAPI)
adapter.getCurrentWeather(city: "New York", completion: { weatherData in
print(weatherData)
})