[Swift Design Pattern 04] Facade (퍼사드)
Facade (퍼사드) - Structural Pattern (구조 패턴)
Facade 패턴은 ios UI 디자인 패턴 중 하나로써 복잡한 프로그램에 대해 간단한 인터페이스를 제공한다.
Client
복잡한 Subsytem을 직접 호출하지 않고 퍼사드를 사용한다.
Facade
퍼사드는 서브 시스템의 기능에 쉽게 접근할 수 있게 해준다.
Additional Facade
퍼사드가 너무 복잡해질 경우, 추가적으로 퍼사드를 생성해 분리해 줄 수 있다.
Subsystem
서브 시스템은 여러 개의 객체들로 구성되며 복잡하다. 서브 시스템은 퍼사드의 존재를 모른다.
서브시스템은 외부 라이브러리 혹은 다른 개발자가 작성한 코드로 생각할 수 있다. 기능을 사용하지만 완전히 이해할 필요가 없는 시스템들이다. 우리가 프레임워크나 라이브러리를 사용할 때 그 이론까지 완벽히 공부할 필요는 없는 것을 생각하면 된다.
When?
- 서브 시스템에 복잡해 접근하기 어려워 더 쉬운 인터페이스를 제공하고 싶을 때
- 서브 시스템을 쪼개고 싶을 때
서브 시스템이 커지고 복잡해지면서 얽히고 얽혀 관리하기가 힘들어진다. 이럴 때 퍼사드를 사용함으로써 서브시스템을 쪼개 계층화 시켜줄 수 있다.
Code
사진을 다운로드 받는 외부 라이브러리를 사용하는 것을 예시로 코드가 작성되었다.
이미지를 다운로드 받는 클래스이다. 이미지를 다운로드 받는 함수 loadImage에 인수가 4개가 있다.
//외부 라이브러리 혹은 다른 사람이 구현한 이미지 다운로드 클래스
private class ImageDownloader {
typealias Completion = (UIImage, Error?) -> ()
typealias Progress = (Int, Int) -> ()
func loadImage(at url: URL?,
placeholder: UIImage? = nil,
progress: Progress? = nil,
completion: Completion) {
/// Image를 다운로드 하는 코드
completion(UIImage(), nil)
}
}
extension을 사용해 UIImageView를 퍼사드로 구현했다.
이 때 이미지를 다운로드 하기 위해서 url 인수 한 개만 있으면 된다.
// 퍼사드
private extension UIImageView {
func downloadImage(at url: URL?) {
print("Start downloading...")
let placeholder = UIImage(named: "placeholder")
ImageDownloader().loadImage(at: url,
placeholder: placeholder,
completion: { image, error in
print("Handle an image...")
self.image = image
})
}
}
url 하나만으로 쉽게 이미지를 다운로드 받을 수 있다.
let imageView = UIImageView()
let url = URL(string: "www.example.com/logo")
imageView.downloadImage(at: url)
Result
Facade 패턴의 장점
1. 복잡한 시스템으로부터 코드를 분리해내 쉽게 사용할 수 있다
복잡한 시스템을 간단하게 사용할 수 있다.
단점
1. 퍼사드가 앱의 모든 객체와 결합된 '신의 객체(a god object)' 가 될 수 있다.
신의 객체란?
객체 하나가 너무 많은 기능을 가지고 있는 경우를 말한다. 마치 신처럼 전지전능한 객체이다.
신이라는 이름 때문에 좋아보이나 사실은 너무 많은 기능을 가지고 있기 때문에 코드가 복잡해지고 유지보수가 힘들어진다.
무분별한 퍼사드 사용은 코드가 객체 코드의 복잡성을 증가시킨다.
Facade 패턴은 더 쉽게 얘기해주는 통역사 같은 역할을 한다.
모든 패턴이 그렇듯 무적인 패턴은 없다.
적당히 사용해야 코드가 복잡해지는 것을 막을 수 있다.