어댑터 패턴은 구조형 디자인 패턴 (Structural design pattern)의 일종으로 인터페이스가 서로 다른 타입이 동일한 형식으로 작동할 수 있도록 만들어 줍니다.
이전 포스트인 전략 패턴과 동일한 상황을 가정합니다. 검색 기능을 개발하고 있으며, 전체, 이미지, 뉴스, 지도 검색 기능이 이미 전략 패턴으로 구현되어 있습니다.
final class SearchFeatureWithPattern {
private var searchStrategy: SearchStrategy = SearchStrategyAll()
func setSearchStrategy(to strategy: SearchStrategy) {
searchStrategy = strategy
}
func searchButtonTapped() {
searchStrategy.search()
}
}
protocol SearchStrategy {
func search()
}
struct SearchStrategyAll: SearchStrategy {
func search() {
print("전체 검색")
}
}
struct SearchStrategyImage: SearchStrategy {
func search() {
print("이미지 검색")
}
}
struct SearchStrategyNews: SearchStrategy {
func search() {
print("뉴스 검색")
}
}
struct SearchStrategyMap: SearchStrategy {
func search() {
print("지도 검색")
}
}
전략 패턴 포스트에서 확인하셨듯이 SearchStrategy
프로토콜을 준수하는 새로운 타입을 추가하는 방식으로 새로운 검색 전략을 추가할 수 있었습니다. 하지만 아래와 같이 다른 회사에서 작성된 검색 기능을 사용하고자 할 때는 어떻게 하여야 할까요?
protocol FindAlgorithm {
func find(global: Bool)
}
struct FindVideoAlgorithm: FindAlgorithm {
func find(global: Bool) {
print("\(global ? "전체 " : "일부 ")" + "동영상 찾기")
}
}
다른 회사에서 개발된 기능인 FindVideoAlgorithm
은 해당 회사에서 사용했던 것으로 추정되는 FindAlgorithm
프로토콜을 따르고 있고, 전체 검색 범위에서 검색할 것인지 여부를 global
이라는 매개변수에 Bool
타입의 인자를 전달하여 검색 작업을 수행합니다.
Adapter pattern
을 적용하면 이렇듯 기존 SearchStrategy
와 다른 인터페이스를 가진 타입을 동일한 인터페이스를 사용하게끔 조정할 수 있습니다.
먼저, 콘센트 규격이 다른 해외에서 사용하는 어댑터와 같이 저희가 원하는 인터페이스를 제공해줄 수 있는 어댑터 타입을 정의합니다.
struct SearchFindAdapter: SearchStrategy {
private var findAlgorithm: FindAlgorithm
init(findAlgorithm: FindAlgorithm) {
self.findAlgorithm = findAlgorithm
}
func search() {
// 내가 `search()`라고 말하면 너는 `find(global: true)`로 알아들으면 돼.
findAlgorithm.find(global: true)
}
}
정의한 어댑터 타입은 이니셜라이저를 통해 변환 대상인 FindAlgorithm
타입의 인스턴스를 프로퍼티로 전달받아 SearchStrategy
인터페이스로 사용할 수 있도록 해줍니다.
어댑터를 활용하여 변환한 FindVideoAlgorithm
은 아래와 같은 방식으로 사용할 수 있습니다.
let searchFeatureWithPattern = SearchFeatureWithPattern()
let searchStrategyVideo = SearchFindAdapter(findAlgorithm: FindVideoAlgorithm())
searchFeatureWithPattern.setSearchStrategy(to: searchStrategyVideo)
searchFeatureWithPattern.searchButtonTapped()