成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一些實(shí)用的編程模式:Options模式

開發(fā) 前端
今天開個(gè)新系列,講一些實(shí)用的編程模式,每個(gè)編程模式學(xué)完后,都能馬上在實(shí)戰(zhàn)中應(yīng)用起來,讓我們寫出更富表達(dá)力、易維護(hù)、好擴(kuò)展、優(yōu)雅億點(diǎn)點(diǎn)的代碼。

[[428512]]

本文轉(zhuǎn)載自微信公眾號(hào)「網(wǎng)管叨bi叨」,作者沒玩游戲的網(wǎng)管。轉(zhuǎn)載本文請(qǐng)聯(lián)系網(wǎng)管叨bi叨公眾號(hào)。

今天開個(gè)新系列,講一些實(shí)用的編程模式,每個(gè)編程模式學(xué)完后,都能馬上在實(shí)戰(zhàn)中應(yīng)用起來,讓我們寫出更富表達(dá)力、易維護(hù)、好擴(kuò)展、優(yōu)雅億點(diǎn)點(diǎn)的代碼。

這些編程模式的示例我會(huì)用Go來演示,但其實(shí)這些模式大多與語言無關(guān),無論你平時(shí)主攻Go、Java還是JavaScript 我覺得都能用上。

為避免貼長篇代碼,我會(huì)適當(dāng)用一些偽代碼,大家理解思路后,可以在我的GitHub倉庫gocookbook找到完整可運(yùn)行的代碼。

公眾號(hào)回復(fù) gocookbook 關(guān)鍵字獲取鏈接,打開后Ctrl+F搜"Options"。

系列第一篇要分享的編程模式是函數(shù)式編程里的Options模式。

Options模式解決什么問題

Options模式可以讓具有多個(gè)可選參數(shù)的函數(shù)或者方法更整潔和好擴(kuò)展,當(dāng)一個(gè)函數(shù)具有五六個(gè)甚至十個(gè)以上的可選參數(shù)時(shí)使用這種模式的優(yōu)勢會(huì)體現(xiàn)的很明顯,我們還是通過一些例子慢慢感受一下。

比如我們要在項(xiàng)目里封裝一個(gè)通用的發(fā)Http請(qǐng)求的工具函數(shù),它的參數(shù)可能會(huì)有哪些呢?因?yàn)槭枪ぞ吆瘮?shù),要做到通用就必然需要定義很多能配置HTTP客戶端的參數(shù),比如:

  1. func HttpRequest(method string, url string, body []byte, headers map[string]string, timeout time.Duration) ... 

函數(shù)簽名里的返回值這里就省略了,太寬影響閱讀,這里大家注意一下。

上面這個(gè)工具函數(shù),如果只是做GET請(qǐng)求的話,很多HTTP客戶端的設(shè)置是不需要設(shè)置的,而且超時(shí)時(shí)間我們一般都會(huì)設(shè)置一個(gè)默認(rèn)的。如果還按普通定義函數(shù)的方法來實(shí)現(xiàn)的話,函數(shù)邏輯里勢必會(huì)有不少判斷空值的邏輯。

  1. if body != nil { 
  2.    // 設(shè)置請(qǐng)求體Data 
  3.   ...... 
  4.  
  5. if headers != nil { 
  6.   // 設(shè)置請(qǐng)求頭 
  7.   ...... 

調(diào)用的時(shí)候,調(diào)用者的代碼也不得不傳一些零值給不需要自定義的配置參數(shù)。

  1. HttpRequest('GET''https://www.baidu.com', nil, nil, 2 * time.Second

如果是Java的話,其實(shí)是可以通過方法的重載解決這個(gè)問題,但是如果可選的參數(shù)是十幾個(gè),各個(gè)調(diào)用方對(duì)可選參數(shù)的順序要求不一樣的話,定義這個(gè)多重載方法顯然不是一個(gè)好的解決方案。

另外一種常用的解決方案是,工具函數(shù)的簽名定義時(shí),不再定義各個(gè)可能需要配置的可選參數(shù),轉(zhuǎn)而定義一個(gè)配置對(duì)象。

  1. type HttpClientConfig struct { 
  2.   timeout time.Duration 
  3.   headers map[string]string 
  4.   body    []byte 
  5.  
  6. func HttpRequest(method string, url string, config *HttpClientConfig) ... 

配置對(duì)象方案的問題

函數(shù)簽名里通過傳遞一個(gè)配置對(duì)象來聚合各種可能的可選參數(shù)這個(gè)方案,對(duì)調(diào)用者來說,比上一種方法看起來簡潔了不少,如果全都是默認(rèn)選項(xiàng)只需要給配置對(duì)象這個(gè)參數(shù)傳遞一個(gè)零值即可。

  1. HttpRequest('GET''https://www.baidu.com', nil) 

但是對(duì)于函數(shù)的實(shí)現(xiàn)方來說,仍然少不了那些選項(xiàng)參數(shù)非零值的判斷,而且因?yàn)榕渲脤?duì)象在函數(shù)外部可以改變,這就有一定幾率配置對(duì)象在函數(shù)內(nèi)部未被使用前被外部程序改變,真正發(fā)生了相關(guān)的BUG,排查起來會(huì)比較頭疼。

可變參數(shù)方案的問題

與配置對(duì)象方案類似,如果單純通過可變參數(shù)來解決這個(gè)問題,也會(huì)有不少問題。

  1. func HttpRequest(method string, url string, options ...interface{}) ... 

雖然參數(shù)是可變的,但是實(shí)現(xiàn)方需要通過遍歷設(shè)置HTTP客戶端的不同選項(xiàng),這就讓可變參數(shù)固定了傳遞順序,調(diào)用方如果想要設(shè)置某個(gè)可選項(xiàng)還得記住參數(shù)順序,切無法直接通過函數(shù)簽名就確定參數(shù)順序,貌似還不如咱們最原始的解決方案。

使用Options模式的方案

最后,我們來說一下使用Options模式怎么解決這個(gè)問題,其實(shí)如果你如果使用過gRPC的話,會(huì)發(fā)現(xiàn)gRPC的SDK里Options模式出現(xiàn)的幾率相當(dāng)高,比如它的客戶端方法可以傳遞不少以with開頭的閉包函數(shù)方法。

  1. client.cc, err = grpc.Dial( 
  2.  "127.0.0.1:12305"
  3.  grpc.WithInsecure(), 
  4.  grpc.WithUnaryInterceptor(...), 
  5.  grpc.WithStreamInterceptor(...), 
  6.  grpc.WithAuthority(...) 

這些配置方法返回的都是一個(gè)名為DialOption的interface。

  1. type DialOption interface { 
  2.  apply(*dialOptions) 
  3.  
  4. func WithInsecure() DialOption { 
  5.  ... 

現(xiàn)在我們就使用Options模式對(duì)我們的工具函數(shù)進(jìn)行一下改造,首先定義一個(gè)契約和配置對(duì)象。

  1. // 針對(duì)可選的HTTP請(qǐng)求配置項(xiàng),模仿gRPC使用的Options設(shè)計(jì)模式實(shí)現(xiàn) 
  2. type requestOption struct { 
  3.  timeout time.Duration 
  4.  data    string 
  5.  headers map[string]string 
  6.  
  7. type Option struct { 
  8.  apply func(option *requestOption) 
  9.  
  10. func defaultRequestOptions() *requestOption { 
  11.  return &requestOption{ // 默認(rèn)請(qǐng)求選項(xiàng) 
  12.   timeout: 5 * time.Second
  13.   data:    ""
  14.   headers: nil, 
  15.  } 

接下來我們要定義的配置函數(shù),每個(gè)都會(huì)設(shè)置請(qǐng)求配置對(duì)象里的某一個(gè)配置。

  1. func WithTimeout(timeout time.Duration) *Option { 
  2.  return &Option
  3.   apply: func(option *requestOption) { 
  4.    option.timeout = timeout 
  5.   }, 
  6.  } 
  7.  
  8. func WithData(data string) *Option { 
  9.  return &Option
  10.   apply: func(option *requestOption) { 
  11.    option.data = data 
  12.   }, 
  13.  } 

那么此時(shí)我們的工具函數(shù)的簽名就應(yīng)用上上面定義的接口契約。

  1. func HttpRequest(method string, url string, options ...*Option) ... 

在其實(shí)現(xiàn)里我們只需要遍歷options這個(gè)可變參數(shù),調(diào)用每個(gè)Option對(duì)象的apply方法對(duì)配置對(duì)象進(jìn)行配置即可,不用在擔(dān)心可變參數(shù)的順序。

  1. func httpRequest(method string, url string, options ...*Option) { 
  2.  reqOpts := defaultRequestOptions() // 默認(rèn)的請(qǐng)求選項(xiàng) 
  3.  for _, opt := range options {      // 在reqOpts上應(yīng)用通過options設(shè)置的選項(xiàng) 
  4.   opt.apply(reqOpts) 
  5.  } 
  6.  // 創(chuàng)建請(qǐng)求對(duì)象 
  7.  req, err := http.NewRequest(method, url, strings.NewReader(reqOpts.data)) 
  8.  
  9.   // 設(shè)置請(qǐng)求頭 
  10.  for key, value := range reqOpts.headers { 
  11.    req.Header.Add(key, value) 
  12.  } 
  13.  // 發(fā)起請(qǐng)求 
  14.   ...... 
  15.  
  16.  return 

總結(jié)

最后我們的HTTP工具函數(shù)的調(diào)用方式就變成了,下面這種更靈活更富表達(dá)力的方式。

  1. HttpRequest("GET", url) 
  2.  
  3. HttpRequest("POST", url, WithHeaders(headers) 
  4.              
  5. HttpRequest("POST", url, WithTimeout(timeout), WithHeaders(headers), WithData(data)) 

從實(shí)現(xiàn)方來看呢?如果后面要給配置對(duì)象里增加其他配置項(xiàng),只需要擴(kuò)充類型的字段,在定義一個(gè)對(duì)應(yīng)的With方法即可,擴(kuò)展性完全在可接受范圍內(nèi)。 

好了Options模式你學(xué)會(huì)沒,想不想趕快用起來,現(xiàn)在公眾號(hào)里回復(fù)關(guān)鍵字 gocookbook 就能獲得完整可運(yùn)行的代碼示例(打開鏈接后記得Ctrl+F搜"Options")。下次再遇到類似的場景后記得把今天學(xué)到的用上呀。

 

責(zé)任編輯:武曉燕 來源: 網(wǎng)管叨bi叨
相關(guān)推薦

2019-08-19 14:56:07

設(shè)計(jì)模式javascript

2017-04-08 17:12:36

設(shè)計(jì)模式抽象策略模式

2014-08-14 09:25:31

Linux串口

2013-07-02 09:43:02

編程策略

2013-07-02 10:18:20

編程編程策略

2024-03-11 15:08:26

Linux操作系統(tǒng)進(jìn)程

2021-10-31 07:36:17

前端JavaScript編程

2016-09-12 17:19:51

JavaScriptArray操作技巧

2013-03-29 09:03:59

iOS實(shí)用小代碼iOS開發(fā)

2021-04-09 10:26:43

Python編程技術(shù)

2022-08-28 23:51:04

編輯器vim代碼

2018-07-23 15:55:28

協(xié)議自定義viewSwift

2014-05-04 11:17:39

Unix命令Linux命令

2011-08-31 10:54:25

Java性能

2018-06-08 08:50:35

編程語言并發(fā)編程

2011-09-13 09:41:59

Python

2021-12-15 10:05:25

軟件開發(fā) 技術(shù)

2022-02-22 12:54:37

微軟Windows

2025-01-20 00:00:06

Vue開發(fā)工具庫

2022-05-17 16:56:33

開發(fā)工具前端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 久久丝袜| 国产精品久久久久久网站 | 99精品国产一区二区三区 | 欧美午夜剧场 | 五月天激情电影 | av中文字幕网| 亚洲国产精品视频一区 | 91伊人| 黄网站在线播放 | 狠狠亚洲 | 欧美成人一区二区三区片免费 | 一区二区三区在线观看视频 | www.伊人.com| 欧美一区二区小视频 | 中日韩av | 久久久久国产精品免费免费搜索 | 色av一区| 欧美在线资源 | 亚洲精品在线91 | 99精品免费在线观看 | 欧美日韩中文字幕在线播放 | 亚洲国产精品久久久 | 国产精品99久久久久久宅男 | 日韩欧美网 | 亚洲高清在线 | 国产欧美日韩精品在线观看 | 久久久久久国产精品免费免费狐狸 | a免费在线| 久草免费视 | 国产一区二区在线免费播放 | 九九热免费在线观看 | 国产视频日韩 | 国产一二三区电影 | 国产精品一区二区三区四区 | 情侣av | 亚洲国产成人精品久久久国产成人一区 | 国产一区二区在线免费观看 | 国产一区视频在线 | 国产999精品久久久 午夜天堂精品久久久久 | 日日欧美 | av天天干 |