GO语言设计模式之--Optional模式 | 青训营

269 阅读2分钟

Go语言的Optional设计模式

引言

在很多情况下,我们都需要实现一些结构体去实现功能或者作为程序的核心,但是结构体的初始化方法是一个很大的问题,例如,当一个结构体拥有很多字段,而我们在实现结构体的过程中可能需要传入非常多的参数,这样对我们的记忆有很大的考验而且不易于维护。

在这种情况下,程序员们想出了一个更好的解决方案:config模式,也就是构造一个和结构体字段相同或相似的config结构体,初始化结构体的时候只需要传入构造好的config即可,这样带来了很大便利,也是很多著名项目的解决方案,例如go-redis。同时也带来一个新的问题,当我们需要改变一个字段的名称时,用户端的字段就要相应的改变,这样给用户带去了很多不便,于是,Optional设计模式应运而生。

Optional模式

Option模式的专业术语为:Functional Options Pattern(函数式选项模式) Option模式为golang的开发者提供了将一个函数的参数设置为可选的功能,也就是说我们可以选择参数中的某几个,并且可以按任意顺序传入参数。 比如针对特殊场景需要不同参数的情况,C++可以直接用重载来写出任意个同名函数,在任意场景调用的时候使用同一个函数名即可;但同样情况下,在golang中我们就必须在不同的场景使用不同的函数,并且参数传递方式可能不同的人写出来是不同的样子,这将导致代码可读性差,维护性差。

Optional的简单实现

package main

import (
	"fmt"
	"time"
)

type Server struct {
	Addr     string
	Port     int
	Protocol string
	Timeout  time.Duration
}

type Option func(*Server)

func WithAddr(addr string) Option {
	return func(server *Server) {
		server.Addr = addr
	}
}

func WithPort(port int) Option {
	return func(server *Server) {
		server.Port = port
	}
}

func WithProtocol(protocol string) Option {
	return func(server *Server) {
		server.Protocol = protocol
	}
}

func WithTimeout(timeout time.Duration) Option {
	return func(server *Server) {
		server.Timeout = timeout
	}
}

func NewServer(options ...Option) *Server {
	s := &Server{}
	for _, o := range options {
		o(s)
	}
	return s
}

func main() {
	s1 := NewServer(WithAddr("localhost"), WithPort(80))
	s2 := NewServer(WithAddr("localhost"), WithPort(8080), WithProtocol("HTTP"))
	s3 := NewServer(WithAddr("localhost"), WithPort(8080), WithProtocol("HTTP"), WithTimeout(time.Hour))
	fmt.Println(s1)
	//&{localhost 80  0s}
	fmt.Println(s2)
	//&{localhost 80  0s}
	fmt.Println(s3)
	//&{localhost 8080 HTTP 1h0m0s}
}

这样我们就实现了一个简单的Optional设计。

Optional的优缺点

优点

  1. 任意顺序传递参数
  2. 支持传递多个参数,并且在参数个数、类型发生变化时保持兼容性

缺点

  1. 增加许多function,成本增大