日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

Golang 常见设计模式之选项模式

發布時間:2024/4/11 asp.net 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Golang 常见设计模式之选项模式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

熟悉 Python 開發的同學都知道,Python 有默認參數的存在,使得我們在實例化一個對象的時候,可以根據需要來選擇性的覆蓋某些默認參數,以此來決定如何實例化對象。當一個對象有多個默認參數時,這個特性非常好用,能夠優雅地簡化代碼。

而 Go 語言從語法上是不支持默認參數的,所以為了實現既能通過默認參數創建對象,又能通過傳遞自定義參數創建對象,我們就需要通過一些編程技巧來實現。對于這些程序開發中的常見問題,軟件行業的先行者們總結了許多解決常見場景編碼問題的最佳實踐,這些最佳實踐后來成為了我們所說的設計模式。其中選項模式在 Go 語言開發中會經常用到。

通常我們有以下三種方法來實現通過默認參數創建對象,以及通過傳遞自定義參數創建對象:

  • 使用多個構造函數

  • 默認參數選項

  • 選項模式

通過多構造函數實現

第一種方式是通過多構造函數實現,下面是一個簡單例子:

package mainimport "fmt"const (defaultAddr = "127.0.0.1"defaultPort = 8000 )type Server struct {Addr stringPort int }func NewServer() *Server {return &Server{Addr: defaultAddr,Port: defaultPort,} }func NewServerWithOptions(addr string, port int) *Server {return &Server{Addr: addr,Port: port,} }func main() {s1 := NewServer()s2 := NewServerWithOptions("localhost", 8001)fmt.Println(s1) // &{127.0.0.1 8000}fmt.Println(s2) // &{localhost 8001} }

這里我們為 Server 結構體實現了兩個構造函數:

  • NewServer:無需傳遞參數即可直接返回 Server 對象

  • NewServerWithOptions :需要傳遞 addr 和 port 兩個參數來構造 Server 對象

如果通過默認參數創建的對象即可滿足需求,不需要對 Server 進行定制時,我們可以使用 NewServer 來生成對象(s1)。而如果需要對 Server 進行定制時,我們則可以使用 NewServerWithOptions 來生成對象(s2)。

通過默認參數選項實現

另外一種實現默認參數的方案,是為要生成的結構體對象定義一個選項結構體,用來生成要創建對象的默認參數,代碼實現如下:

package mainimport "fmt"const (defaultAddr = "127.0.0.1"defaultPort = 8000 )type Server struct {Addr stringPort int }type ServerOptions struct {Addr stringPort int }func NewServerOptions() *ServerOptions {return &ServerOptions{Addr: defaultAddr,Port: defaultPort,} }func NewServerWithOptions(opts *ServerOptions) *Server {return &Server{Addr: opts.Addr,Port: opts.Port,} }func main() {s1 := NewServerWithOptions(NewServerOptions())s2 := NewServerWithOptions(&ServerOptions{Addr: "localhost",Port: 8001,})fmt.Println(s1) // &{127.0.0.1 8000}fmt.Println(s2) // &{localhost 8001} }

我們為 Server 結構體專門實現了一個 ServerOptions 用來生成默認參數,調用 NewServerOptions 函數即可獲得默認參數配置,構造函數 NewServerWithOptions 接收一個 *ServerOptions 類型作為參數。所以我們可以通過以下兩種方式來完成功能:

  • 直接將調用 NewServerOptions 函數的返回值傳遞給 NewServerWithOptions 來實現通過默認參數生成對象(s1)

  • 通過手動構造 ServerOptions 配置來生成定制對象(s2)

通過選項模式實現

以上兩種方式雖然都能夠完成功能,但卻有以下缺點:

  • 通過多構造函數實現的方案需要我們在實例化對象時分別調用不同的構造函數,代碼封裝性不強,會給調用者增加使用負擔。

  • 通過默認參數選項實現的方案需要我們預先構造一個選項結構,當使用默認參數生成對象時代碼看起來比較冗余。

而選項模式可以讓我們更為優雅地解決這個問題。代碼實現如下:

package mainimport "fmt"const (defaultAddr = "127.0.0.1"defaultPort = 8000 )type Server struct {Addr stringPort int }type ServerOptions struct {Addr stringPort int }type ServerOption interface {apply(*ServerOptions) }type FuncServerOption struct {f func(*ServerOptions) }func (fo FuncServerOption) apply(option *ServerOptions) {fo.f(option) }func WithAddr(addr string) ServerOption {return FuncServerOption{f: func(options *ServerOptions) {options.Addr = addr},} }func WithPort(port int) ServerOption {return FuncServerOption{f: func(options *ServerOptions) {options.Port = port},} }func NewServer(opts ...ServerOption) *Server {options := ServerOptions{Addr: defaultAddr,Port: defaultPort,}for _, opt := range opts {opt.apply(&options)}return &Server{Addr: options.Addr,Port: options.Port,} }func main() {s1 := NewServer()s2 := NewServer(WithAddr("localhost"), WithPort(8001))s3 := NewServer(WithPort(8001))fmt.Println(s1) // &{127.0.0.1 8000}fmt.Println(s2) // &{localhost 8001}fmt.Println(s3) // &{127.0.0.1 8001} }

乍一看我們的代碼復雜了很多,但其實調用構造函數生成對象的代碼復雜度是沒有改變的,只是定義上的復雜。

我們定義了 ServerOptions 結構體用來配置默認參數。因為 Addr 和 Port 都有默認參數,所以 ServerOptions 的定義和 Server 定義是一樣的。但有一定復雜性的結構體中可能會有些參數沒有默認參數,必須讓用戶來配置,這時 ServerOptions 的字段就會少一些,大家可以按需定義。

同時,我們還定義了一個 ServerOption 接口和實現了此接口的 FuncServerOption 結構體,它們的作用是讓我們能夠通過 apply 方法為 ServerOptions 結構體單獨配置某項參數。

我們可以分別為每個默認參數都定義一個 WithXXX 函數用來配置參數,如這里定義的 WithAddr 和 WithPort ,這樣用戶就可以通過調用 WithXXX 函數來定制需要覆蓋的默認參數。

此時默認參數定義在構造函數 NewServer 中,構造函數的接收一個不定長參數,類型為 ServerOption,在構造函數內部通過一個 for 循環調用每個傳進來的 ServerOption 對象的 apply 方法,將用戶配置的參數依次賦值給構造函數內部的默認參數對象 options 中,以此來替換默認參數,for 循環執行完成后,得到的 options 對象將是最終配置,將其屬性依次賦值給 Server 即可生成新的對象。

總結

通過 s2 和 s3 的打印結果可以發現,使用選項模式實現的構造函數更加靈活,相較于前兩種實現,選項模式中我們可以自由的更改其中任意一項或多項默認配置。

雖然選項模式確實會多寫一些代碼,但多數情況下這都是值得的。比如 Google 的 gRPC 框架 Go 語言實現中創建 gRPC server 的構造函數 NewServer 就使用了選項模式,感興趣的同學可以看下其源碼的實現思想其實和這里的示例程序如出一轍。

以上就是我關于 Golang 選項模式的一點經驗,希望今天的分享能夠給你帶來一些幫助。

總結

以上是生活随笔為你收集整理的Golang 常见设计模式之选项模式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。