当前位置: 移动技术网 > IT编程>脚本编程>Go语言 > Go语言设计模式之函数式选项模式

Go语言设计模式之函数式选项模式

2019年10月26日  | 移动技术网IT编程  | 我要评论

go语言设计模式之函数式选项模式

本文主要介绍了go语言中函数式选项模式及该设计模式在实际编程中的应用。

为什么需要函数式选项模式?

最近看源码的时候,发现了一段关于服务注册的代码如下:

type options struct {
    broker    broker.broker
    cmd       cmd.cmd
    client    client.client
    server    server.server
    registry  registry.registry
    transport transport.transport

    // before and after funcs
    beforestart []func() error
    beforestop  []func() error
    afterstart  []func() error
    afterstop   []func() error

    // other options for implementations of the interface
    // can be stored in a context
    context context.context
}

func newoptions(opts ...option) options {
    opt := options{
        broker:    broker.defaultbroker,
        cmd:       cmd.defaultcmd,
        client:    client.defaultclient,
        server:    server.defaultserver,
        registry:  registry.defaultregistry,
        transport: transport.defaulttransport,
        context:   context.background(),
    }

    for _, o := range opts {
        o(&opt)
    }

    return opt
}

当时呢,也不是很明白newoptions这个构造函数为什么要这么写,但是后面在微信群里看到有人也再发类似的代码问为什么要这么写,后来在群里讨论的时候才知道了这是一种设计模式–函数式选项模式

可能大家看到现在也不是很明白我说的问题到底是什么,我把它简单提炼一下。

我们现在有一个结构体,定义如下:

type option struct {
    a string
    b string
    c int
}

现在我们需要为其编写一个构造函数,我们可能会写成下面这种方式:

func newoption(a, b string, c int) *option {
    return &option{
        a: a,
        b: b,
        c: c,
    }
}

上面的代码很好理解,也是我们一直在写的。有什么问题吗?

我们现在来思考以下两个问题:

  1. 我们可能需要为option的字段指定默认值
  2. option的字段成员可能会发生变更

选项模式

我们先定义一个optionfunc的函数类型

type optionfunc func(*option)

然后利用闭包为每个字段编写一个设置值的with函数:

func witha(a string) optionfunc {
    return func(o *option) {
        o.a = a
    }
}

func withb(b string) optionfunc {
    return func(o *option) {
        o.b = b
    }
}

func withc(c int) optionfunc {
    return func(o *option) {
        o.c = c
    }
}

然后,我们定义一个默认的option如下:

var (
    defaultoption = &option{
        a: "a",
        b: "b",
        c: 100,
    }
)

最后编写我们新版的构造函数如下:

func newoption2(opts ...optionfunc) (opt *option) {
    opt = defaultoption
    for _, o := range opts {
        o(opt)
    }
    return
}

测试一下:

func main() {
    x := newoption("nazha", "小王子", 10)
    fmt.println(x)
    x = newoption2()
    fmt.println(x)
    x = newoption2(
        witha("沙河娜扎"),
        withc(250),
    )
    fmt.println(x)
}

输出:

&{nazha 小王子 10}
&{a b 100}
&{沙河娜扎 b 250}

这样一个使用函数式选项设计模式的构造函数就实现了。这样默认值也有了,以后再要为option添加新的字段也不会影响之前的代码。

推荐阅读:

go 函数式选项模式

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网