class FBSharer: Sharing {
func post(message: String) -> Bool {
print("Message \(message) shared on Facebook")
return true
}
}
class TwitterSharer: Sharing {
func post(message: String) -> Bool {
print("Message \(message) shared on Twitter")
return true
}
}
Adaptee : 새로이 도입한 서비스, 기본적인 구현을 변경할 수 없다.
// Third-party class - we cannot modify its implementation
public class RedditPoster {
public func share(text: String,
completionHandler: ((Error?) -> Void)?) {
print("Message \(text) posted to Reddit")
completionHandler?(nil)
}
}
새롭게 도입한 서비스가 특정 사유로 인해 변경할 수 없거나, 기능을 유지하고 싶은 경우가 있다.
기존의 사용하던 서비스에 통합시키기 위해,
아래와 같이 Sharing이라는 Target 인터페이스를 extension을 통해 구현해준다.
// Sharer utility
// A naive approach to integrate the incompatible RedditPoster type
public class Sharer {
private let services: [Platform: Sharing] = [.facebook: FBSharer(),
.twitter: TwitterSharer(),
.reddit: RedditPoster()]
private lazy var redditPoster = RedditPoster()
public func share(message: String,
serviceType: Platform) {
guard let service = services[serviceType] else {
return
}
service.post(message: message)
}
public func shareEverywhere(message: String) {
for service in services.values {
service.post(message: message)
}
}
}
위의 Sharer 클래스에 존재하는 services들은 Sharing이라는 Target 인터페이스를 공유한다.
따라서 forEach 문에서 service.post()와 같은 식의 메서드 호출이 가능하다.
테스트
// Testing
let sharer = Sharer()
sharer.shareEverywhere(message: "First post!")
위의 예제에서는 extension을 이용하여 단순히 Target에 대해서 새롭게 구현해주고 있다. 이러한 방식도 유의미하지만, 핑구님의 블로그에 있는 예시처럼 새로운 service가 가진 메서드를 한번 Wrapping하여 사용하는 것이 많은 부분에 사용될 수 있는 좋은 아이디어인 것 같다.
Adapter Pattern이란?
어댑터 패턴은 기존에 사용하던 Service와 새로운 Service를 같은 목적으로 사용할 수 있도록 하는 디자인 패턴이다. 새로운 Service에 동일한 인터페이스를 채택하여 기존의 Service와 호환될 수 있도록 만들어 준다.
Target : 기존에 사용하던 Service가 따르던 프로토콜 & 새로운 Service를 함께 사용하려면 따라야 하는 Protocol
Client : 기존에 존재하던 Service들
Adaptee : 새로이 도입한 서비스, 기본적인 구현을 변경할 수 없다.
새롭게 도입한 서비스가 특정 사유로 인해 변경할 수 없거나, 기능을 유지하고 싶은 경우가 있다. 기존의 사용하던 서비스에 통합시키기 위해, 아래와 같이 Sharing이라는
Target
인터페이스를 extension을 통해 구현해준다.결과물 : 기존의 서비스와 새로운 서비스를 통합하여 만든 서비스
위의 Sharer 클래스에 존재하는 services들은 Sharing이라는 Target 인터페이스를 공유한다. 따라서
forEach
문에서service.post()
와 같은 식의 메서드 호출이 가능하다.테스트