728x90
반응형
Delegate Pattern (위임패턴)
1. 위임 패턴이란?
객체가 직접 작업을 수행하지 않고 다른 도우미 객체에게 그 작업을 맡기는 디자인 패턴. 이 도우미 객체를 위임 객체(Delegate)라고 한다.
2. 위임 패턴의 대표적 예시 - by lazy() 프로퍼티 초기화 지연
- 지연 초기화(lazy initialization)
- 객체의 일부분을 초기화하지 않고 남겨두었다가, 실제로 그 부분의 값이 필요할 경우 초기화한다.
- 지연 초기화를 사용하는 경우
- 초기화 과정에서 자원을 많이 사용하거나
- 객체를 사용할 때 마다 꼭 초기화하지 않아도 되는 프로퍼티일 때
- 예시
- Person 클래스: 자신이 작성한 메일 리스트를 제공한다
- 이메일들이 db에 저장되어있으며, 불러오면 시간이 걸린다 가정하자.
- 그래서 이메일 프로퍼티의 값을 최초로 사용할 때 단 한번만 이메일을 db에서 가져올 것이다.
- 이메일들이 db에 저장되어있으며, 불러오면 시간이 걸린다 가정하자.
- loadEmail() 함수를 호출 할 때, 초기화 된다.
- Person 클래스: 자신이 작성한 메일 리스트를 제공한다
class Person(val name: String) {
val emails by lazy { loadEmail(this) }
}
class Email
fun loadEmail(person: Person): List<Email> {
println("${person.name}의 이메일을 가져옴")
return listOf()
}
- by 키워드의 역할
- by 뒤에는 위임에 쓰일 객체를 사용한다.
- lazy 함수에 의해 제공된 객체에게 초기화 작업을 위임하고 있다. 즉 lazy가 대신 그 값을 초기화해주고있다.
- lazy 함수
- getValue 메서드가 들어있는 객체를 반환한다.
- 위임 관례에 따라 Delegate 클래스는 getValue ( 변경가능한 프로퍼티라면 setValue도 사용)이 필요하므로 by 키워드와 함께 많이 사용된다.
3. 위임 프로퍼티의 장점 느껴보기
❓ 이런 경우를 생각해보자
- 어떤 객체의 프로퍼티가 바뀔때마다 리스너에게 변경 통지를 보내고싶다.
- Person 클래스의 나이나 급여가 바뀌면 리스너에게 알려주고싶다.
- 어떤 객체를 UI에 표시하는 경우, 그 객체가 바뀌면 자동으로 UI를 변경하고 싶다면?
→ PropertyChangeSupport나 PropertyChangeEvent를 사용해 이런 통지를 처리하는 경우가 많다.
- PropertyChangeSupport: 리스너 목록을 관리한다.
- PropertyChangeEvent: 이벤트가 들어오면 목록의 모든 리스너에게 이벤트를 통지한다.
open class PropertyChangeAware {
protected val changedSupport = PropertyChangeSupport(this)
fun addPropertyChangeListener(listener: PropertyChangeListener) {
changedSupport.addPropertyChangeListener(listener)
}
fun removePropertyChangeListener(listener: PropertyChangeListener){
changedSupport.removePropertyChangeListener(listener)
}
}
❌ 프로퍼티 변경 통지를 직접 구현하기 (field 키워드)
fun main() {
val person = Person("Alice", 20, 100)
person.addPropertyChangeListener(
PropertyChangeListener { event ->
println("Property ${event.propertyName} changed" + "from ${event.oldValue} to ${event.newValue}")
}
)
person.age = 30
person.salary = 1000
//Property age changedfrom 20 to 30
//Property salary changedfrom 100 to 1000
}
class Person(val name: String, age: Int, salary: Int) : PropertyChangeAware() {
var age: Int = age
set(newValue) {
val oldValue = field
field = newValue
changedSupport.firePropertyChange(
"age", oldValue, newValue
)
}
var salary: Int = salary
set(newValue) {
val oldValue = field
field = newValue
changedSupport.firePropertyChange(
"salary", oldValue, newValue
)
}
}
- field 키워드의 역할
- getter나 setter에서만 사용가능한 내부 변수
- 실제 설정된 값을 가르킨다.
❌ 도우미 클래스를 통해 프로퍼티 변경 통지 구현하기
class ObservableProperty(
val propName: String, var propValue: Int,
val changeSupport: PropertyChangeSupport
) {
fun getValue(): Int = propValue
fun setValue(newValue: Int) {
val oldValue = propValue
propValue = newValue
changeSupport.firePropertyChange(propName, oldValue, newValue)
}
}
class Person(val name: String, age: Int, salary: Int) : PropertyChangeAware() {
val _age = ObservableProperty("age", age, changedSupport)
var age: Int
get() = _age.getValue()
set(value) {
_age.setValue(value)
}
val _salary = ObservableProperty("salary", salary, changedSupport)
var salary: Int
get() = _salary.getValue()
set(value) {
_salary.setValue(value)
}
}
⭕️ 위임 프로퍼티를 통해 프로퍼티 변경 통지 받기
//코틀린 관례에 맞게 수정한다.
class ObservableProperty(var propValue: Int, val changeSupport: PropertyChangeSupport) {
operator fun getValue(p: Person, prop: KProperty<*>): Int = propValue
operator fun setValue(p: Person, prop: KProperty<*>, newValue: Int) {
val oldValue = propValue
propValue = newValue
changeSupport.firePropertyChange(prop.name, oldValue, newValue)
}
}
class Person(
val name: String, age: Int, salary: Int
) : PropertyChangeAware() {
var age: Int by ObservableProperty(age, changedSupport)
var salary : Int by ObservableProperty(salary, changedSupport)
}
https://en.wikipedia.org/wiki/Delegation_pattern
Delegation pattern - Wikipedia
From Wikipedia, the free encyclopedia Design pattern in object-oriented programming In software engineering, the delegation pattern is an object-oriented design pattern that allows object composition to achieve the same code reuse as inheritance. In delega
en.wikipedia.org
https://kotlinlang.org/docs/delegation.html
Delegation | Kotlin
kotlinlang.org
https://kotlinlang.org/docs/delegated-properties.html
Delegated properties | Kotlin
kotlinlang.org
728x90
반응형
'Kotlin' 카테고리의 다른 글
Kotlin14. null 문제, 스코프함수 (0) | 2023.08.13 |
---|---|
Kotlin13. class의 다른 확장 - Pair, 확장메소드/프로퍼티.. (0) | 2023.08.13 |
Kotlin12. class의 다른 확장 - Delegation, observable... (0) | 2023.08.13 |
Kotlin11. interface, abstract, Singleton (0) | 2023.08.13 |
Kotlin10. class와 OOP (0) | 2023.08.06 |