본문 바로가기
프로그래밍/Swift

Swift 패턴 이야기- 빌더 패턴(builder)

by Mr-후 2021. 7. 21.
반응형

빌더 패턴은 복잡한 객체의 생성을 도우면서 어떻게 이러한 객체들을 생성하는지에 대한 프로세스를 강제한다. 일반적으로 빌더 패턴에서는 복잡한 타입으로부터 생성 로직을 분리하며, 다른 타입을 추가한다. 빌더 패턴은 타입의 서로 다른 결과물을 생성하는 데 동일한 생성 프로세스를 사용하게 해준다. 

 

빌더 패턴을 구현하는데 사용할 수 있는 방법에는 두 가지가 있다. 첫 번째 방법은 구체적인 방법으로, 원래의 복잡한 객체를 설정하는 정보를 가진 여러 가지의 빌더 타입을 갖는 방식이다. 두 번째 방법은 모든 설정 가능한 옵션을 기본 값으로 설장하는 단일 빌더 타입을 사용해 빌더 패턴을 구현하며 필요하다면 옵션 값을 변경하는 방식이다. 

 

빌더 패턴 구현

struct BugerOld {
    var name: String
    var patties: Int
    var bacon: Bool
    var cheese: Bool 
    var pickles: Bool
    var ketchup: Bool
    var mustard: Bool
    var lettuuce: Bool
    var tomato: Bool
    init(name: String, patties: Int, bacon: Bool, cheese: Bool, pickles: Bool, ketchup: Bool 
        mustard: Bool, lettuce: Bool, tomato: Bool) {
        self.name = name
        self.patties = patties
        self.bacon = bacon
        self.cheese = cheese
        self.pickles = pickles
        self.ketchup = ketchup
        self.mustard = mustard
        self.lettuce = lettuce
        self.tomato = tomato 
     }
 }
 


//햄버거를 생성한다. 
var burgerOld = BurgerOld(name: "Hamburger", patties: 1, bacon: false, cheese: false,
    ... tomato: false)
    
치즈버거를 생성한다. 
var burgerOld = BurgerOld(name: "Cheeseburger", patties: 1, bacon: false, cheese: true,
    .... tomato: false)

이러한 방식으로 BugerOld타이비의 인스트턴스를 생성하는 데에는 많은 코드가 필요하다. 

 

빌더 타입 사용 하는 방법 

protocol BurgerBuilder {
    var name: String{get}
    var patties: Int {get}
    var bacon:  Bool {get}
    var cheese: Bool {get}
    ...
}


// HamburgerBuilder구조체와 CheeseBurgerBuilder구조체에서는 각각 요구되는 프로퍼티에 단순한 값을 정의
// 더 복잡한 타입에서는 추가적인 리소스를 초기화해야 할지도 ... 

struct HamburgerBuilder: BurgerBuilder {
   let name = "Burger"
   let patties = 1
   let bacon = false 
   let cheese = false 
   ...
}

struct CheeseBurgerBuilder: BurgerBuilder {
   let name = "Burger"
   let patties = 1
   let bacon = false 
   let cheese = false 
   ...
}

//Burger구초체는 자기 자신의 인스턴스를 생성하는데 BurgerBuilder 프로토콜의 인스턴스를 사용할 것이다. 
struct Burger {
   var name: String
   var patties: Int
   var bacon: Bool
   var cheese: Bool
   ....
   
   init(builder: BugerBuilder) {
       self.name = builder.name
       self.patties = builder.patties
       self.bacon = builder.bacon
       self.cheese = builder.cheese
       ...
   }
   
   func showBurger() { 
       print("name: \(name) ")
       print("patties: \(patties) ")
       print("bacon: \(bacon) ")
       print("cheese: \(cheese) ")
   }
   
   
}

설계된 프로토콜과 패턴을 이용하는 예

//햄버거를 생성한다. 
var myBurger = Buger(builder: HamburgerBuilder())
myBuger.showBurger()

//토마토가 들어간 치즈버거를 생성한다. 
var myCheeseBugerBuilder = CheeseBurgerBuilder()
var myCheeseBurger = Burger(builder: myCheeseBugerBuilder) 

//토마토를 뺀다. 
myCheeseBurger.tomato = false 
myCheeseBurger.showBurger()

타입의 인스턴스를 생성하는데 매우 길고 복잡한 생성자 커맨드를 발견하게 된다면 생성자를 단순화하는 데 사용할 수 있느지를 살펴보는 데 빌더패턴을 검토하길 추천. 

 

 

 

반응형