Builder 패턴을 알아보기전에 아래 링크를 참고하여 golang의 type embedding 문법을 보고 오시길 바랍니다.
https://up-to-date-items.tistory.com/114
이제 Builder 패턴을 알아보겠습니다.
1
2
3
4
5
6
7
8
9
|
type Person struct {
// 주소 관련
Address string
PostCode string
// 직업 관련
JobType string
Company string
}
|
cs |
위처럼 Person 구조체가 있다면 해당 구조체를 선언하려면 아래처럼 필요한 인자들을 나열해야 합니다.
1
2
3
4
5
6
|
p := Person{
Address: "Seoul...",
PostCode: "14931",
JobType: "IT",
Company: "Google",
}
|
cs |
예제의 간략화를 위해 구조체에 4개의 필드만 지정했지만 훨씬 더 많다면 보기에도 불편하고 선언시에도 불편합니다.
Builder 패턴을 이용하면 조금 더 직관적이고 각 필드마다 독립적인 기능을 추가할 수도 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
type PersonBuilder struct {
person *Person
}
// PersonBuilder의 receiver function들을 사용할 수 있음
type PersonJobBuilder struct {
PersonBuilder
}
// PersonBuilder의 receiver function들을 사용할 수 있음
type PersonAddressBuilder struct {
PersonBuilder
}
|
cs |
우선 직업 관련 필드들을 담당할 구조체와 주소 관련 필드들을 나누기 위해 위처럼 구조체를 분리하였습니다.
또한, 위 코드의 주석에 적힌대로 PersonJobBuilder와 PersonAddressBuilder는 PersonBuilder의 메서드들을 사용할 수 있습니다.
(이에 대한 설명은 맨 위 golang의 type embedding 링크에 있습니다.)
이제 위 3개의 구조체들의 메서드들을 작성해보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
type PersonBuilder struct {
person *Person
}
func NewPersonBuilder() *PersonBuilder {
// 각 필드는 비워둔채로 초기화함
return &PersonBuilder{&Person{}}
}
func (pb *PersonBuilder) Build() *Person {
return pb.person
}
func (pb *PersonBuilder) Work() *PersonJobBuilder {
return &PersonJobBuilder{*pb}
}
func (pb *PersonBuilder) Live() *PersonAddressBuilder {
return &PersonAddressBuilder{*pb}
}
|
cs |
먼저 PersonBuilder 타입의 메서드들입니다.
Build 메서드는 나중에 Person type을 인자로 받는 함수들을 위해 만들어진 것이고
Work와 Live 메서드는 보다시피 각각의 구조체를 return 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
type PersonJobBuilder struct {
PersonBuilder
}
func (pjb *PersonJobBuilder) At(company string) *PersonJobBuilder {
pjb.person.Company = company
return pjb
}
func (pjb *PersonJobBuilder) JobType(jobType string) *PersonJobBuilder {
pjb.person.JobType = jobType
return pjb
}
|
cs |
다음은 PersonJobBuilder의 메서드들입니다.
각 메서드들을 통해 필드를 설정할 수 있습니다. 위에서는 정말 set 기능만 하였지만 각 함수내에서 여러가지 조건을 넣어서 사용자의 실수를 방지할 수 있습니다.
중요한 부분은 각 메서드마다 *PersonJobBuilder 타입을 return한 것인데 이렇게 return 함으로써 chaining이 가능해집니다.
1
2
3
4
|
pb := NewPersonBuilder()
pb.Work()
.JobType("IT")
.At("Google")
|
cs |
위처럼 chaining이 가능해집니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
type PersonAddressBuilder struct {
PersonBuilder
}
func (pab *PersonAddressBuilder) At(address string) *PersonAddressBuilder {
pab.person.Address = address
return pab
}
func (pab *PersonAddressBuilder) PostCode(postcode string) *PersonAddressBuilder {
pab.person.PostCode = postcode
return pab
}
|
cs |
마지막으로 PersonAddressBuilder의 메서드들이며 마찬가지로 chaining이 가능하게 하였습니다.
이렇게 만들어진 코드들로 아래와 같은 코드가 작성가능해집니다.
1
2
3
4
5
6
7
|
pb := NewPersonBuilder()
pb.Live().At("서울시....").PostCode("15941")
.Work().JobType("IT").At("Google")
person := pb.Build()
fmt.Println(person)
|
cs |
이렇게 Builder 패턴을 알아보았습니다.
'golang > design pattern' 카테고리의 다른 글
golang design pattern #6 Bridge (0) | 2021.11.12 |
---|---|
golang design pattern #5 Adapter (0) | 2021.11.12 |
golang design pattern #4 Singleton (0) | 2021.11.11 |
golang design pattern #3 Prototype (0) | 2021.11.11 |
golang design pattern #2 Factory (0) | 2021.11.10 |