Golang 选项设计模式

引入问题: 现有一个结构体,再声明一个用于初始化该结构体的构造方法, 进行对结构体字段赋值

package main

import "fmt"

// 声明options结构体
type Options struct {
    str1 string
    str2 string
    int1 int
    int2 int
}

// 声明构造方法进行初始化结构体
func InitOptions() *Options {
    return &Options{}
}

func main() {
    options := InitOptions()
    fmt.Printf("%#v", options)
}

普通方法实现

在构造方法中声明结构体的每一个字段值,且要和结构体中的字段位置进行对照

package main

import "fmt"

// 声明options结构体
type Options struct {
    str1 string
    str2 string
    int1 int
    int2 int
}

// 声明构造方法进行初始化结构体
func InitOptions(str1 string, str2 string, int1 int, int2 int) *Options {
    options := &Options{}
    options.str1 = str1
    options.str2 = str2
    options.int1 = int1
    options.int2 = int2
    return options
}

func main() {
    options := InitOptions("a", "b", 1, 2)
    fmt.Printf("%#v", options)
}

此方法的问题: 当结构体每增加一个字段都需要进行对构造函数就行修改,并且对结构体字段增加的个数和字段类型具有不确定性,如果要修改的化这种方法看着比较繁琐,而且代码看着也比较 low

第二种普通写法

看上面的写法字段的个数和字段的类型都是不确定的,我们可以将构造参数变为一个可变的传参方式,并且传入的参数是一个 interface 类型的,之后通过遍历参数给结构体赋值

package main

import "fmt"

// 声明options结构体
type Options struct {
    str1 string
    str2 string
    int1 int
    int2 int
}

// 声明构造方法进行初始化结构体
func InitOptions(opts ...interface{}) *Options {
    options := &Options{}
    for index, val := range opts {
        switch index {
        case 1:
            v, _ := val.(string)
            options.str1 = v
        case 2:
            v, _ := val.(string)
            options.str2 = v
        case 3:
            v, _ := val.(int)
            options.int1 = v

        case 4:
            v, _ := val.(int)
            options.int2 = v
        }
    }

    return options
}

func main() {
    options := InitOptions("a", "b", 1, 2)
    fmt.Printf("%#v", options)
}

这种方法看着也是比较繁琐,但是我们确定了构造函数需要的参数个数和类型是不确定的,那我们就引入使用选项设计模式进行改造

选项设计模式实现

  1. 声明一个 Option 变量类型,类型为一个函数类型,函数类型接收一个指针类型的 Options 结构体
  2. 构造函接受一个可变长度的 Option 变量类型
  3. 之后没增加一个字段创建一个指定格式类型的函数,传入构造函数即可初始化结构体

代码如下:

package main

import "fmt"

// 声明options结构体
type Options struct {
    str1 string
    str2 string
    int1 int
    int2 int
}

// 声明一个变量类型,变量接收一个Options结构体的指针类型
type Option func(opts *Options)

// 声明构造方法进行初始化结构体
func InitOptions(opts ...Option) *Options {
    options := &Options{}
    for _, opt := range opts {
        opt(options)
    }
    return options
}

func WithOptionStr1(str string) Option {
    return func(opts *Options) {
        opts.str1 = str
    }
}

func WithOptionStr2(str string) Option {
    return func(opts *Options) {
        opts.str2 = str
    }
}

func WithOptionInt1(i int) Option {
    return func(opts *Options) {
        opts.int1 = i
    }
}

func WithOptionInt2(i int) Option {
    return func(opts *Options) {
        opts.int2 = i
    }
}

func main() {
    options := InitOptions(
        WithOptionStr1("a"),
        WithOptionStr2("b"),
        WithOptionInt1(1),
        WithOptionInt2(2),
    )
    fmt.Printf("%#v", options)
}

猜你喜欢

转载自www.cnblogs.com/zhichaoma/p/12509110.html