[Kotlin] Delgate Pattern

silver·2022년 11월 29일
0

저번에도 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개의 댓글