[Kotlin] Delgate Pattern

silver·2022년 11월 29일

저번에도 Delegate 관련 개념에 대해서 알아보았지만 이번에는 그때 알아보지 못한 overvable과 vetoable에 대해 알아보려 한다.

Delegate Pattern

어떠한 기능을 자기 자신이 처리하지 않고 다른 객체에 일을 위임시켜 그 객체가 일을 처리하게끔 하도록 하는 디자인 패턴을 Delgate Pattern 이라고 한다.

Kotlin 의 Delegates - observable, vetoable

어떤 데이터의 값이 변경되었는지 쉽게 알아 낼 수 있도록하는 delegate 개념이다.
옵저버 패턴과 비슷하다고 볼 수 있다.

Observable

말 그대로 프로퍼티를 observable하게 만들어 주는 것이다.
프로퍼티의 데이터가 변할 때마다 callback을 받을 수 있는 구조이다.

public inlinie fun <T> observable(initialValue: T, 
								  crossinline onChange: (property: KProperty<*>, 
                                  						 oldValue: T, 
                                  						 newValue: T) -> Unit): ReadWriteProperty<Any?, T>
= object : ObservableProperty<T>(initialValue) {
  	override fun afterChange(property: KProperty<*>, 
        					 oldValue: T, 
                             newValue: T)
	= onChange(property, oldValue, newValue)
}
  • initialValue: 프로퍼티의 초기값
  • onChange: 프로퍼티의 값이 변경됐을 때 호출되는 callback 함수
    - 프로퍼티와 oldValue(이전 값), newValue(새로운 값)을 전달

example

var observableField: Int by Delegates.ovservable(0) { property, old, new ->
	println("old: $old, new: $new")
}

fun main() {
	println(observableField) // 0
    
    observableField = 1
    
    println(observableField) // 1
}

결과

0
old: 0, new: 1
1

Vetoable

observable과 거의 유사하지만 반환값이 존재한다.

public inline fun <T> vetoable(initialValue T, 
							   crossinline onChange: (property: KProperty<*>, 
                               						  oldValue: T, 
                                                      newValue: T) -> Boolean) : ReadWriteProperty<Any?, T> 
= object: ObservableProperty<T>(initialValue) {
  override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean 
  = onChange(property, oldValue, newValue)
}

vetoable 의 onChange 함수는 Boolean 값을 반환한다.
여기서 반환 값이 true 일 때만 프로퍼티의 값을 갱신한다.

example

var vetoableField: Int by Delegates.vetoable(0) { property, old, new -> 
	println("old: $old, new $new")
    new % 2 == 0
}

fun main() {
	println(vetoableField)
    vetoableField = 1
    println(vetoableField)
    vetoableField = 2
    println(vetoableField)
}

결과

0
old: 0, new: 1
0
old: 0, new: 2
2

0개의 댓글