Backend
Builder Pattern
뭉크테크
2026. 8. 1. 00:06
정의
- 빌더 패턴은 최종 객체 생성에 필요한 여러 설정값을 Builder 객체에 임시로 저장한 뒤, 그 설정값을 바탕으로 최종 목적 객체를 생성하는 패턴이다.
필요한 이유
class Computer(
val cpu: String,
val ram: Int,
val storage: Int,
val gpu: String?,
val wifi: Boolean,
val bluetooth: Boolean
)
val computer = Computer("Intel i7", 32, 1000, "RTX 5070", true, true)
- 각 값이 무엇인지 코드만 보고 바로 구분하기 힘들며, 매개 변수 순서도 틀릴 가능성 존재한다.(가독성 문제)
- 선택항목이 많아지면 필요없는 값까지 어쩔 수 없이 null, false, 0 같은 기본값들로 일일이 채워야하는 불편함 또한 존재한다.
코드
전체 코드
class Computer private constructor(
val cpu: String,
val ram: Int,
val storage: Int,
val gpu: String?,
val wifi: Boolean,
val bluetooth: Boolean
) {
class Builder {
private var cpu: String = ""
private var ram: Int = 0
private var storage: Int = 0
private var gpu: String? = null
private var wifi: Boolean = false
private var bluetooth: Boolean = false
fun cpu(cpu: String): Builder {
this.cpu = cpu
return this
}
fun ram(ram: Int): Builder {
this.ram = ram
return this
}
fun storage(storage: Int): Builder {
this.storage = storage
return this
}
fun gpu(gpu: String): Builder {
this.gpu = gpu
return this
}
fun wifi(wifi: Boolean): Builder {
this.wifi = wifi
return this
}
fun bluetooth(bluetooth: Boolean): Builder {
this.bluetooth = bluetooth
return this
}
fun build(): Computer {
require(cpu.isNotBlank()) { "CPU는 필수입니다." }
require(ram > 0) { "RAM은 0보다 커야 합니다." }
require(storage > 0) { "저장 공간은 0보다 커야 합니다." }
return Computer(cpu, ram, storage, gpu, wifi, bluetooth)
}
}
}
객체 생성
val computer = Computer.Builder()
.cpu("Intel i7")
.ram(32)
.storage(1000)
.gpu("RTX 5070")
.wifi(true)
.bluetooth(true)
.build()
- 객체 생성을 위한 값들을 별도의 Builder 객체 단계적으로 저장한 뒤, 마지막에 최종 객체를 생성한다.
주 생성자 입력값 선언
class Computer private constructor(
val cpu: String,
val ram: Int,
val storage: Int,
val gpu: String?,
val wifi: Boolean,
val bluetooth: Boolean
)
- Computer 객체 생성을 위해 위 선언된 변수들을 데이터 타입에 맞춰 빌더 클래스 method에 기입해야한다.
빌더 클래스
class Builder {
private var cpu: String = ""
private var ram: Int = 0
private var storage: Int = 0
private var gpu: String? = null
private var wifi: Boolean = false
private var bluetooth: Boolean = false
fun cpu(cpu: String): Builder {
this.cpu = cpu
return this
}
fun ram(ram: Int): Builder {
this.ram = ram
return this
}
fun storage(storage: Int): Builder {
this.storage = storage
return this
}
fun gpu(gpu: String): Builder {
this.gpu = gpu
return this
}
fun wifi(wifi: Boolean): Builder {
this.wifi = wifi
return this
}
fun bluetooth(bluetooth: Boolean): Builder {
this.bluetooth = bluetooth
return this
}
fun build(): Computer {
require(cpu.isNotBlank()) { "CPU는 필수입니다." }
require(ram > 0) { "RAM은 0보다 커야 합니다." }
require(storage > 0) { "저장 공간은 0보다 커야 합니다." }
return Computer(cpu, ram, storage, gpu, wifi, bluetooth)
}
}
- 최종 객체를 생성하기 전에 객체 생성에 필요한 값들을 임시로 저장하기위한 클래스이다.
- Kotlin 컴파일러는 Computer 라는 클래스 내부에 Builder 라는 중첩 클래스가 있다는 것을 인지하며, JVM에서 실행할 수 있도록 일반적으로 Computer.class와 Computer$Builder.class라는 별도의 클래스 파일로 컴파일한다.
- Computer.Builder()를 호출하면 최종 객체 생성에 필요한 값들을 저장할 Builder 객체만 생성된다. 이후 cpu(), ram() 등의 메서드를 호출하면 사용자가 전달한 값이 Builder 객체 내부의 각 필드에 저장된다.
- 이 메서드들은 현재 Builder 객체의 참조값을 가진 this 를 반환하므로 메서드 체이닝이 가능하다. 즉, 하나의 메서드 호출이 끝난 뒤, 동일한 Builder 객체의 참조값이 반환되고 그 반환된 객체를 대상으로 다음 메서드를 연속해서 호출이 가능하다.
- 그리고 최종적으로 build() 라는 메서드 호출시, Build 클래스 인스턴스에 저장된 값들을 그대로 Computer 클래스 생성자 호출시 프로퍼티 초기화값으로 사용되기에, 최종적으로 사용자가 Builer 클래스 인스턴스에 설정했던 값들을 가진 Computer 객체를 생성한다.