KOTLIN · 디자인패턴
비지터 패턴 (Visitor)
sealed class와 when을 활용하여 객체 구조를 변경하지 않고 새 연산을 추가하는 비지터 패턴입니다.
디자인패턴고급visitorsealed-classpattern-matchingexpression
핵심 설명
sealed class와 when을 활용하여 객체 구조를 변경하지 않고 새 연산을 추가하는 비지터 패턴입니다.
Kotlin code
sealed class Expr {
data class Num(val value: Double) : Expr()
data class Add(val left: Expr, val right: Expr) : Expr()
data class Mul(val left: Expr, val right: Expr) : Expr()
data class Neg(val expr: Expr) : Expr()
}
// 비지터: 새 연산 추가 (클래스 수정 불필요)
fun eval(expr: Expr): Double = when (expr) {
is Expr.Num -> expr.value
is Expr.Add -> eval(expr.left) + eval(expr.right)
is Expr.Mul -> eval(expr.left) * eval(expr.right)
is Expr.Neg -> -eval(expr.expr)
}
fun prettyPrint(expr: Expr): String = when (expr) {
is Expr.Num -> expr.value.toString()
is Expr.Add -> "(${prettyPrint(expr.left)} + ${prettyPrint(expr.right)})"
is Expr.Mul -> "(${prettyPrint(expr.left)} * ${prettyPrint(expr.right)})"
is Expr.Neg -> "-${prettyPrint(expr.expr)}"
}
fun depth(expr: Expr): Int = when (expr) {
is Expr.Num -> 0
is Expr.Add -> 1 + maxOf(depth(expr.left), depth(expr.right))
is Expr.Mul -> 1 + maxOf(depth(expr.left), depth(expr.right))
is Expr.Neg -> 1 + depth(expr.expr)
}
fun main() {
// (3 + 4) * -(2)
val expr = Expr.Mul(
Expr.Add(Expr.Num(3.0), Expr.Num(4.0)),
Expr.Neg(Expr.Num(2.0))
)
println("식: ${prettyPrint(expr)}")
println("값: ${eval(expr)}")
println("깊이: ${depth(expr)}")
}학습 팁
Kotlin에서는 sealed class + when 조합이 전통적인 Visitor 인터페이스보다 간결합니다. 새 연산은 함수를 추가하면 됩니다.
주의할 점
sealed class에 새 하위 타입을 추가하면 모든 when 분기를 수정해야 합니다. 타입이 자주 바뀌면 전통적인 OOP 방식이 나을 수 있습니다.
자주 묻는 질문
비지터 패턴 (Visitor)란 무엇인가요?
sealed class와 when을 활용하여 객체 구조를 변경하지 않고 새 연산을 추가하는 비지터 패턴입니다.
비지터 패턴 (Visitor) 학습 시 주의할 점은 무엇인가요?
sealed class에 새 하위 타입을 추가하면 모든 when 분기를 수정해야 합니다. 타입이 자주 바뀌면 전통적인 OOP 방식이 나을 수 있습니다.
Continue Learning
Kotlin 학습을 이어가세요
총 200개의 독립 HTML 학습 문서 중 하나입니다. 각 문서는 고유 URL과 canonical 메타데이터를 가집니다.