Go에서의 빌더 패턴
Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 107개 중 80번째.
Builder Pattern은 복잡한 객체의 구축 과정과 그 표현을 분리합니다. Functional Options 패턴과 달리 Builder는 객체를 단계별로 구성하는 메서드를 갖춘 전용 builder 구조체를 사용합니다.
HTTP 요청을 위한 builder를 구현하는 방법은 다음과 같습니다:
type Request struct {
method string
url string
headers map[string]string
body string
}
type RequestBuilder struct {
request *Request
}
func NewRequestBuilder() *RequestBuilder {
return &RequestBuilder{
request: &Request{
headers: make(map[string]string),
},
}
}
func (b *RequestBuilder) Method(m string) *RequestBuilder {
b.request.method = m
return b
}
func (b *RequestBuilder) URL(u string) *RequestBuilder {
b.request.url = u
return b
}
func (b *RequestBuilder) Header(key, value string) *RequestBuilder {
b.request.headers[key] = value
return b
}
func (b *RequestBuilder) Build() *Request {
return b.request
}각 method는 builder pointer를 반환하여 method chaining을 가능하게 합니다. Build() method는 constructed object를 최종 확정하고 반환합니다:
req := NewRequestBuilder().
Method("POST").
URL("https://api.example.com").
Header("Content-Type", "application/json").
Build()Builder 패턴은 객체에 여러 구성 단계가 필요하거나 특정 구성 순서를 강제하려는 경우에 탁월합니다. 특히 변경 불가능한 객체를 생성하거나 구성 과정 자체에 검증이 필요한 경우에 유용합니다.
챌린지
쉬움Builder Pattern을 사용하여 이메일 메시지 composer를 만들어 봅시다! 이메일 메시지에는 recipients, CC, subject, body, attachments와 같은 많은 선택적 구성 요소가 있으므로, method chaining을 사용한 단계별 구성에 완벽한 대상입니다.
코드를 두 개의 파일로 구성합니다:
email.go: 이메일 구조와 builder를 Define합니다.다음 fields를 가진
Emailstruct를 Create합니다:from(string)to(slice of strings)cc(slice of strings)subject(string)body(string)
구성 중인 Email에 대한 pointer를 holds하는
EmailBuilderstruct를 Create합니다. initialized Email과 함께 새 builder를 반환하는NewEmailBuilder()를 Implement합니다. (to와cc에는 empty slices를 사용합니다.)다음 builder methods를 Add합니다. 각 method는 chaining을 위해
*EmailBuilder를 반환합니다:From(address string)- sender를 설정합니다To(address string)-toslice에 recipient를 adds합니다CC(address string)-ccslice에 recipient를 adds합니다Subject(subject string)- subject line을 설정합니다Body(body string)- email body를 설정합니다
constructed
*Email을 반환하는Build()method를 Add합니다.Finally, Email에 다음 format의 string을 반환하는
Summary()method를 Add합니다:From: [from] To: [comma-separated to addresses] CC: [comma-separated cc addresses or "none"] Subject: [subject] Body: [body]main.go: builder를 사용하여 이메일 메시지를 Build하고 표시합니다.sender address를 Read한 다음, recipients의 number와 각 recipient address를 Read합니다. 다음으로 CC recipients의 number와 각 CC address를 Read합니다. Finally, subject와 body를 Read합니다.
EmailBuilder를 method chaining과 함께 사용하여 이메일을 construct한 다음 summary를 print합니다.
다음 inputs가 제공됩니다:
- Line 1: Sender address
- Line 2: Number of recipients
- Following lines: 각 recipient address
- Next line: Number of CC recipients
- Following lines: 각 CC address
- Next line: Subject
- Final line: Body
예를 들어, 다음이 주어졌다고 합시다:
alice@company.com
2
bob@company.com
carol@company.com
1
manager@company.com
Weekly Report
Please find the weekly report attached.출력은 다음과 같아야 합니다:
From: alice@company.com
To: bob@company.com, carol@company.com
CC: manager@company.com
Subject: Weekly Report
Body: Please find the weekly report attached.그리고 다음이 주어졌다고 합시다:
support@service.com
1
customer@email.com
0
Your Ticket Update
Your support ticket has been resolved.출력은 다음과 같아야 합니다:
From: support@service.com
To: customer@email.com
CC: none
Subject: Your Ticket Update
Body: Your support ticket has been resolved.builder를 사용하면 반복되는 To() calls를 통해 여러 recipients를 한 번에 하나씩 Add할 수 있으며, optional fields가 많더라도 pattern이 construction process를 깔끔하고 읽기 쉽게 유지한다는 점에 주목하세요.
직접 해보기
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// 발신자 주소 읽기
from, _ := reader.ReadString('\n')
from = strings.TrimSpace(from)
// 수신자 수 읽기
toCountStr, _ := reader.ReadString('\n')
toCount, _ := strconv.Atoi(strings.TrimSpace(toCountStr))
// 각 수신자 주소 읽기
toAddresses := make([]string, toCount)
for i := 0; i < toCount; i++ {
addr, _ := reader.ReadString('\n')
toAddresses[i] = strings.TrimSpace(addr)
}
// CC 수신자 수 읽기
ccCountStr, _ := reader.ReadString('\n')
ccCount, _ := strconv.Atoi(strings.TrimSpace(ccCountStr))
// 각 CC 주소 읽기
ccAddresses := make([]string, ccCount)
for i := 0; i < ccCount; i++ {
addr, _ := reader.ReadString('\n')
ccAddresses[i] = strings.TrimSpace(addr)
}
// 제목 읽기
subject, _ := reader.ReadString('\n')
subject = strings.TrimSpace(subject)
// 본문 읽기
body, _ := reader.ReadString('\n')
body = strings.TrimSpace(body)
// TODO: 메서드 체이닝으로 EmailBuilder를 사용하여 이메일을 구성하세요
// NewEmailBuilder()로 시작한 다음 From(), To(), CC(), Subject(), Body()를 체이닝하세요
// 마지막으로 Build()를 호출하여 Email을 얻으세요
// TODO: Summary() 메서드를 사용하여 이메일 요약을 출력하세요
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
8에러 처리와 OOP
error 인터페이스사용자 정의 에러 타입에러 래핑 (fmt.Errorf)센티넬 에러errors.Is()와 errors.As()Panic, Defer, Recover요약 - 파일 파서직접 연습해 보세요: 온라인 Go 컴파일러