생성 패턴 - 빌더 패턴 (Builder Pattern)

French Marigold·2024년 5월 16일
0

디자인패턴

목록 보기
10/10
post-thumbnail

정의

  • 빌더 패턴(Builder Pattern)은 객체의 생성과 객체 내부에 들어갈 요소들을 분리해내어 “다양한 표현될 수 있는 유연성을 제공”하는 패턴이다.

빌더 패턴 (Builder Pattern) 의 구조

  • Builder ⇒
    • Product의 속성에 값을 할당하는 메소드로 이루어진 프로토콜 타입
    • 해당 프로토콜 내부에는 build() 라는 메소드가 존재하며, 이 메소드는 조립이 완료된 후 Product를 리턴하기 위해 사용되는 메소드이다.
  • Concrete Builder ⇒
    • Builder 내부에 존재하는 메소드들을 구체적으로 구현하는 영역.
  • Director
    • Builder 영역에서 제공하는 메소드를 이용해 다양한 형태의 Product를 조립하는 영역.
  • Product
    • Director가 Builder를 이용해 뭔가를 만들어내기 위해 필요로 하는 “기본 양식”

Swift로 빌더 패턴 적용 과정 예시

  1. 회사 사원들의 프로필을 저장하는 프로그램을 제작한다고 가정해보자. 먼저 신입이 들어올 경우, 저장해야 할 인적사항들을 모아놓은 클래스 객체를 생성한다. 이 객체는 기본 양식으로 이 객체에 Builder를 할당하여 다양한 형태의 인적 프로필을 생성해낼 것이다.
// Product
class UserProfile {
    var name: String?
    var email: String?
    var birthdate: Date?
    var profilePictureURL: URL?
    
    // UserProfile 객체의 내용을 간단히 출력하는 함수
    func describe() {
        print("Name: \(name ?? "No name")")
        print("Email: \(email ?? "No email")")
        print("Birthdate: \(birthdate?.description ?? "No birthdate")")
        print("Profile Picture URL: \(profilePictureURL?.absoluteString ?? "No URL")")
    }
}
  1. 프로필의 기본 양식 (Product)에 값을 할당할 메소드를 소유하고 있는 프로토콜 Builder를 생성한다.
// Builder
protocol UserProfileBuilder {
    func setName(_ name: String) -> UserProfileBuilder
    func setEmail(_ email: String) -> UserProfileBuilder
    func setBirthdate(_ date: Date) -> UserProfileBuilder
    func setProfilePictureURL(_ url: URL) -> UserProfileBuilder
    func build() -> UserProfile
}
  1. Builder 내부의 메소드들을 구체적으로 구현하는 Concrete Builder를 생성한다.
// Concrete Builder
class ConcreteUserProfileBuilder: UserProfileBuilder {
    private var userProfile = UserProfile()
    
    func setName(_ name: String) -> UserProfileBuilder {
        userProfile.name = name
        return self
    }
    
    func setEmail(_ email: String) -> UserProfileBuilder {
        userProfile.email = email
        return self
    }
    
    func setBirthdate(_ date: Date) -> UserProfileBuilder {
        userProfile.birthdate = date
        return self
    }
    
    func setProfilePictureURL(_ url: URL) -> UserProfileBuilder {
        userProfile.profilePictureURL = url
        return self
    }
    
    func build() -> UserProfile {
        return userProfile
    }
}
  1. Builder 영역에서 제공하는 메소드를 이용해 다양한 형태의 사원 프로필을 만들어낼 수 있다.
// Director
let builder = ConcreteUserProfileBuilder()

let leo = builder.setName("레오")
    .setEmail("leo@example.com")
    .setBirthdate(Date())
    .setProfilePictureURL(URL(string: "https://example.com/profile.jpg")!)
    .build()

let elly = builder.setName("엘리")
    .setEmail("elly@example.com")
    .setBirthdate(Date())
    .setProfilePictureURL(URL(string: "https://example.com/profile.jpg")!)
    .build()

leo.describe()
elly.describe()

패턴 사용 시기

  • 어떤 클래스 객체 내에 “생성자 매개변수가 너무 많을 때” ⭐️⭐️ 에는 생성자보단 빌더 패턴을 사용할 것을 권장한다.

패턴의 장점

  • 생성자 방식으로 객체를 생성할 경우, 매개변수가 많아질 수록 코드의 가독성이 급격하게 떨어지게 된다. 반면 빌더 패턴을 사용하면 훨씬 더 직관적인 코드를 작성할 수 있게 된다.
  • 재사용성에 용이하다. (빌더 패턴을 이용해 여러 가지 다양한 객체가 생성될 수 있다.)

패턴의 단점

  • 코드의 복잡성이 증가한다. 디자인 패턴의 공통적인 단점이다.

참고 문헌

profile
꽃말 == 반드시 오고야 말 행복

1개의 댓글

comment-user-thumbnail
2024년 5월 17일

빌더패턴에서 무조건 할당해야 하는 프로퍼티가 있을 때 해당 값을 할당하도록 강제할 수 있는 방법이 있을까요?
생성자를 사용한다면 생성자 파라미터에 해당 값을 추가해서 객체 생성하려면 무조건 넣게 할 수 있을텐데
빌더패턴은 프로퍼티 할당을 메서드의 호출로 진행하다보니 필수적으로 있어야 하는 프로퍼티인데 할당을 깜빡할 수 있을 것 같아서요

답글 달기