在Golang的套件中常看一種稱為Functional Option Pattern的寫法,好處為建構物件時可彈性的設定需要的屬性。
Functional Options Pattern的特色是透過函式來實現設定參數到建構的物件屬性中。先定義一個函式類型,傳入參數為要設定屬性的物件,然後建立回傳該函式類型的函式來設定不同的物件屬性(這段話太抽象請直接看以下範例)。
例如下面要設定屬性的物件為Employee
。
建立一個函式類型Option func(e *Employee)
。
建立多個回傳實現Option
函式的函式,例如WithName(name string)
,參數為要設定的Employee
屬性值。在回傳的Option
函式實現中將輸入參數設定到Employee
的屬性。
在Employee
的建構式NewEmployee
傳入必要的參數,例如id
,和不確定數量的...Option
參數。在建構式中先建立Employee
物件,然後遍歷...Option
時傳入Employee
物件為參數。
main.go
package main
import (
"fmt"
)
type Employee struct {
Id string
Name string
Email string
Phone string
Age int
}
func (e Employee) String() string {
return fmt.Sprintf("{id=%s, name=%s, email=%s, phone=%s, age=%d}",
e.Id, e.Name, e.Email, e.Phone, e.Age)
}
type Option func(e *Employee)
func (option Option) Apply(e *Employee) {
option(e)
}
func NewEmployee(id string, options ...Option) *Employee {
e := &Employee{
Id: id,
}
for _, option := range options {
option(e)
}
return e
}
func WithName(name string) Option {
return func(e *Employee) {
e.Name = name
}
}
func WithEmail(email string) Option {
return func(e *Employee) {
e.Email = email
}
}
func WithPhone(phone string) Option {
return func(e *Employee) {
e.Phone = phone
}
}
func WithAge(age int) Option {
return func(e *Employee) {
e.Age = age
}
}
func main() {
e := NewEmployee(
"1",
WithName("john"),
WithAge(33),
)
fmt.Println(e)
WithEmail("john@abc.com").Apply(e)
WithPhone("111-222-3333").Apply(e)
fmt.Println(e)
}
測試
執行後印出以下:
{id=1, name=john, email=, phone=, age=33}
{id=1, name=john, email=john@abc.com, phone=111-222-3333, age=33}
沒有留言:
張貼留言