의존성 : Dependency
- 객체 지향 프로그래밍에서 Dependency는 '서로 다른 객체 사이에 의존 관계가 있는 것'을 말함
- 즉, 의존하는 객체가 수정되면, 다른 객체도 영향을 받는다는 것
import UIKit
// 의존성이 있는 프로토콜
protocol Talk {
func sayHi()
}
// Talk 프로토콜을 채택하여 구현한 클래스
class FriendTalk : Talk{
func sayHi() {
print("FriendTalk - sayHi()")
}
}
// 의존성을 주입받은 클래스
class LetsTalk{
private let talk : Talk
init(){
self.talk = FriendTalk() //FriendTalk 인스턴스를 직접 생성하여 주입
}
func sayHi(){
talk.sayHi()
}
}
- LetsTalk 클래스의 생성자에서 FriendTalk 인스턴스를 직접 생성하여 talk 프로퍼티에 할당 -> 의존성 문제 발생
- 이 부분에서 생성자 주입을 사용하지 않고 의존성을 직접 생성하고 주입하기 때문에 의존성 문제가 발생함
- FriendTalk 객체에 중요한 수정이나 오류가 발생한다면 LetsTalk 객체도 영향을 받을 수 있다
- 의존성을 가지는 코드가 많아진다면, 재활용성이 떨어지고 매번 의존성을 가지는 객체들을 함께 수정해주어야 함 -> 의존성 주입으로 해결
Dependency Injection (의존성 주입)
* 사용 이유
- Unit Test가 용이해짐
- 코드의 재활용성 높여줌
- 객체 간의 의존성을 줄이거나 없앨 수 있음
- 객체 간의 결합도를 낮추면서 유연한 코드를 작성 가능
* Injection (주입)
- 외부에서 객체를 생성해서 넣는 것
* 사용 방법
1. 프로토콜 정의
// 의존성이 있는 프로토콜
protocol Talk {
var saying : String {get set}
func sayHi()
}
- 프로토콜은 Swift에서 인터페이스에 해당하는 역할을 수행하는 기능
- 프로토콜을 채택하는 클래스는 프로토콜의 속성과 메서드 구현을 강제화 함
2. 프로토콜을 채택하여 구현한 클래스 작성
// Talk 프로토콜을 채택하여 구현(준수)한 클래스
class FriendTalk : Talk{
var saying : String = "FriendTalk 입니다."
func sayHi() {
print("FriendTalk - sayHi()")
}
}
// Talk 프로토콜을 채택하여 구현(준수)한 클래스
class ParentsTalk : Talk{
var saying : String = "ParentsTalk 입니다."
func sayHi() {
print("ParentsTalk - sayHi()")
}
}
- Talk 프로토콜을 채택한 FriendTalk, ParentsTalk 클래스를 구현
- 두 클래스는 각자 saying 속성과 sayHi() 메서드를 구현해야 함
3. 프로토콜에 대한 의존성을 주입 받는 클래스 작성
// 의존성을 주입 받은 클래스
class LetsTalk{
var talkProvider : Talk
var saying : String{
talkProvider.saying
}
init(talk : Talk){
self.talkProvider = talk
}
func sayHi(){
talkProvider.sayHi()
}
}
- Talk 프로토콜을 준수하는 어떤 객체도 받을 수 있는 talkProvider 프로퍼티 선언
- talkProvider의 saying 값을 반환하는 saying 프로퍼티 선언
- init(talk : Talk) 생성자를 통해 외부에서 Talk 프로토콜을 준수하는 객체를 주입 받아 talkProvider에 할당
- 프로토콜을 준수하는 객체를 클래스 내부에서 생성하여 할당하는 것이 아닌 외부에서 받아와 할당하므로 의존성 문제를 해결함
4. 프로토콜을 준수한 객체를 외부에서 생성하여 할당
let letsTalk = LetsTalk(talk: FriendTalk())
letsTalk.sayHi()
print(letsTalk.saying)
print("===================")
let letsTalk2 = LetsTalk(talk: ParentsTalk())
letsTalk2.sayHi()
print(letsTalk2.saying)
- letsTalk 인스턴스를 생성할 때 FriendTalk() 인스턴스를 주입하여 LetsTalk 클래스의 객체 생성
- letsTalk 인스턴스의 talkProvider 프로퍼티엔 FriendTalk 객체가 할당
- 즉, letsTalk 객체는 FriendTalk 클래스를 의존성으로 주입 받아 그 기능을 활용하고 의존성 객체의 속성 값이나 메서드에 접근 가능
전체 코드
import UIKit
// 의존성이 있는 프로토콜
protocol Talk {
var saying : String {get set}
func sayHi()
}
// Talk 프로토콜을 채택하여 구현(준수)한 클래스
class FriendTalk : Talk{
var saying : String = "FriendTalk 입니다."
func sayHi() {
print("FriendTalk - sayHi()")
}
}
// Talk 프로토콜을 채택하여 구현(준수)한 클래스
class ParentsTalk : Talk{
var saying : String = "ParentsTalk 입니다."
func sayHi() {
print("ParentsTalk - sayHi()")
}
}
// 의존성을 주입 받은 클래스
class LetsTalk{
var talkProvider : Talk
var saying : String{
talkProvider.saying
}
init(talk : Talk){
self.talkProvider = talk
}
func sayHi(){
talkProvider.sayHi()
}
}
let letsTalk = LetsTalk(talk: FriendTalk())
letsTalk.sayHi()
print(letsTalk.saying)
print("===================")
let letsTalk2 = LetsTalk(talk: ParentsTalk())
letsTalk2.sayHi()
print(letsTalk2.saying)
참고)
https://80000coding.oopy.io/68ee8d89-5d05-449d-87e2-5fba84d604ca
https://www.youtube.com/watch?v=Jau0a0IvveY
'Swift' 카테고리의 다른 글
Swift - 고차함수 (compactMap, flatMap) (0) | 2023.07.12 |
---|---|
Swift - 고차함수 (map, filter, reduce) (0) | 2023.07.11 |
Swift - 문서화 (퀵헬프 표시 주석 작성 방법) (0) | 2023.07.09 |
Swift - 디자인 패턴(생성 관련) - 빌더 패턴 (0) | 2023.07.08 |
Swift - 디자인 패턴(생성 관련) - 싱글톤 (0) | 2023.07.08 |