網頁

2023/10/17

Golang Functional Options Pattern簡介

在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)
}

github


測試

執行後印出以下:

{id=1, name=john, email=, phone=, age=33}
{id=1, name=john, email=john@abc.com, phone=111-222-3333, age=33}


沒有留言:

張貼留言