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

探討兩種 Option 編程模式的實(shí)現(xiàn)

開發(fā) 前端
option編程模式大家一定熟知,但是其寫法不唯一,主要是形成了兩個(gè)版本的option設(shè)計(jì),本文就探討一下其中的優(yōu)缺點(diǎn)。

option編程模式的引出

在我們?nèi)粘i_發(fā)中,經(jīng)常在初始化一個(gè)對(duì)象時(shí)需要進(jìn)行屬性配置,比如我們現(xiàn)在要寫一個(gè)本地緩存庫,設(shè)計(jì)本地緩存結(jié)構(gòu)如下:

type cache struct {
// hashFunc represents used hash func
HashFunc HashFunc
// bucketCount represents the number of segments within a cache instance. value must be a power of two.
BucketCount uint64
// bucketMask is bitwise AND applied to the hashVal to find the segment id.
bucketMask uint64
// segment is shard
segments []*segment
// segment lock
locks []sync.RWMutex
// close cache
close chan struct{}
}

在這個(gè)對(duì)象中,字段hashFunc、BucketCount是對(duì)外暴露的,但是都不是必填的,可以有默認(rèn)值,針對(duì)這樣的配置,因?yàn)镚o語言不支持重載函數(shù),我們就需要多種不同的創(chuàng)建不同配置的緩存對(duì)象的方法:

func NewDefaultCache() (*cache,error){}
func NewCache(hashFunc HashFunc, count uint64) (*cache,error) {}
func NewCacheWithHashFunc(hashFunc HashFunc) (*cache,error) {}
func NewCacheWithBucketCount(count uint64) (*cache,error) {}

這種方式就要我們提供多種創(chuàng)建方式,以后如果我們要添加配置,就要不斷新增創(chuàng)建方法以及在當(dāng)前方法中添加參數(shù),也會(huì)導(dǎo)致NewCache方法會(huì)越來越長,為了解決這個(gè)問題,我們就可以使用配置對(duì)象方案:

type Config struct {
HashFunc HashFunc
BucketCount uint64
}

我們把非必填的選項(xiàng)移動(dòng)config結(jié)構(gòu)體內(nèi),創(chuàng)建緩存的對(duì)象的方法就可以只提供一個(gè),變成這樣:

func DefaultConfig() *Config {}
func NewCache(config *Config) (*cache,error) {}

這樣雖然可以解決上述的問題,但是也會(huì)造成我們?cè)贜ewCache方法內(nèi)做更多的判空操作,config并不是一個(gè)必須項(xiàng),隨著參數(shù)增多,NewCache的邏輯代碼也會(huì)越來越長,這就引出了option編程模式,接下來我們就看一下option編程模式的兩種實(shí)現(xiàn)。

option編程模式一

使用閉包的方式實(shí)現(xiàn),具體實(shí)現(xiàn):

type Opt func(options *cache)

func NewCache(opts ...Opt) {
c := &cache{
close: make(chan struct{}),
}
for _, each := range opts {
each(c)
}
}

func NewCache(opts ...Opt) (*cache,error){
c := &cache{
hashFunc: NewDefaultHashFunc(),
bucketCount: defaultBucketCount,
close: make(chan struct{}),
}
for _, each := range opts {
each(c)
}
......
}

func SetShardCount(count uint64) Opt {
return func(opt *cache) {
opt.bucketCount = count
}
}

func main() {
NewCache(SetShardCount(256))
}

這里我們先定義一個(gè)類型Opt,這就是我們option的func型態(tài),其參數(shù)為*cache,這樣創(chuàng)建緩存對(duì)象的方法是一個(gè)可變參數(shù),可以給多個(gè)options,我們?cè)诔跏蓟椒ɡ锩嫦冗M(jìn)行默認(rèn)賦值,然后再通過for loop將每一個(gè)options對(duì)緩存參數(shù)的配置進(jìn)行替換,這種實(shí)現(xiàn)方式就將默認(rèn)值或零值封裝在NewCache中了,新增參數(shù)我們也不需要改邏輯代碼了。但是這種實(shí)現(xiàn)方式需要將緩存對(duì)象中的field暴露出去,這樣就增加了一些風(fēng)險(xiǎn),其次client端也需要了解Option的參數(shù)是什么意思,才能知道要怎樣設(shè)置值,為了減少client端的理解度,我們可以自己提前封裝好option函數(shù),例如上面的SetShardCount,client端直接調(diào)用并填值就可以了。

option編程模式二

這種option編程模式是uber推薦的,是在第一版本上面的延伸,將所有options的值進(jìn)行封裝,并設(shè)計(jì)一個(gè)Option interface,我們先看例子:

type options struct {
hashFunc HashFunc
bucketCount uint64
}

type Option interface {
apply(*options)
}

type Bucket struct {
count uint64
}

func (b Bucket) apply(opts *options) {
opts.bucketCount = b.count
}

func WithBucketCount(count uint64) Option {
return Bucket{
count: count,
}
}

type Hash struct {
hashFunc HashFunc
}

func (h Hash) apply(opts *options) {
opts.hashFunc = h.hashFunc
}

func WithHashFunc(hashFunc HashFunc) Option {
return Hash{hashFunc: hashFunc}
}

func NewCache(opts ...Option) (*cache,error){
o := &options{
hashFunc: NewDefaultHashFunc(),
bucketCount: defaultBucketCount,
}
for _, each := range opts {
each.apply(o)
}
.....
}

func main() {
NewCache(WithBucketCount(128))
}

這種方式我們使用Option接口,該接口保存一個(gè)未導(dǎo)出的方法,在未導(dǎo)出的options結(jié)構(gòu)上記錄選項(xiàng),這種模式為client端提供了更多的靈活性,針對(duì)每一個(gè)option可以做更細(xì)的custom function設(shè)計(jì),更加清晰且不暴露cache的結(jié)構(gòu),也提高了單元測(cè)試的覆蓋性,缺點(diǎn)是當(dāng)cache結(jié)構(gòu)發(fā)生變化時(shí),也要同時(shí)維護(hù)option的結(jié)構(gòu),維護(hù)復(fù)雜性升高了。

總結(jié)

這兩種實(shí)現(xiàn)方式都很常見,其都有自己的優(yōu)缺點(diǎn),采用閉包的實(shí)現(xiàn)方式,我們不需要為維護(hù)option,維護(hù)者的編碼也大大減少了,但是這種方式需要export對(duì)象中的field,是有安全風(fēng)險(xiǎn)的,其次是client端需要了解對(duì)象結(jié)構(gòu)中參數(shù)的意義,才能寫出option參數(shù),不過這個(gè)可以通過自定義option方法來解決;采用接口的實(shí)現(xiàn)方式更加靈活,每一個(gè)option都可以做精細(xì)化設(shè)計(jì),不需要export對(duì)象中的field,并且很容易進(jìn)行調(diào)試和測(cè)試,缺點(diǎn)是需要維護(hù)兩套結(jié)構(gòu),當(dāng)對(duì)象結(jié)構(gòu)發(fā)生變更時(shí),option結(jié)構(gòu)也要變更,增加了代碼維護(hù)復(fù)雜性。

實(shí)際應(yīng)用中,我們可以自由變化,不能直接定義哪一種實(shí)現(xiàn)就是好的,凡事都有兩面性,適合才是最好的。

責(zé)任編輯:武曉燕 來源: Golang夢(mèng)工廠
相關(guān)推薦

2010-07-13 10:47:18

Perl面向?qū)ο?/a>

2010-07-13 14:54:15

Perl面向?qū)ο缶幊?/a>

2024-06-06 08:32:52

.NET框架代碼

2010-06-02 10:47:37

SVN開發(fā)

2009-06-29 18:11:40

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

2011-02-23 12:49:31

KonquerorEmbedded

2010-08-26 15:15:18

DB2備份

2010-02-02 14:32:32

Python線程編程

2010-06-02 15:29:06

SVN版本控制

2012-11-29 10:45:31

2021-10-09 09:15:01

Windows 11安全模式系統(tǒng)

2012-10-16 09:40:38

洗牌算法

2010-07-14 10:30:26

Perl多線程

2010-10-14 14:33:15

MySQL多表聯(lián)查

2021-12-08 10:47:35

RabbitMQ 實(shí)現(xiàn)延遲

2011-08-09 13:50:01

iPhone動(dòng)畫UIView

2009-12-17 13:45:58

VS 2008外殼

2010-08-31 09:31:58

Silverlight

2022-03-10 07:39:33

.NET部署模式

2022-02-02 21:29:39

路由模式Vue-Router
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 夜夜草视频 | 国产精品高清在线 | 国产成人福利在线观看 | 在线a视频网站 | 成人午夜精品 | 91亚洲精华国产 | 亚洲欧洲成人av每日更新 | 日韩毛片| 国产精品久久久久久影院8一贰佰 | 九热在线| 婷婷激情五月网 | 精品美女 | 久久久久久亚洲精品不卡 | 国产欧美久久一区二区三区 | 久久久久久久久久一区 | 狠狠躁天天躁夜夜躁婷婷老牛影视 | 啪啪免费 | 一级特黄色毛片 | 天堂在线www| 91久久综合| 中文字幕免费在线 | 国产精品一区一区三区 | 久久久久久久久久久久91 | 一级a性色生活片久久毛片波多野 | 蜜桃日韩| 色婷婷九月| 午夜手机在线视频 | 欧美一区不卡 | 在线免费看黄 | 国产99久久精品一区二区永久免费 | 99热视| 亚洲第一av网站 | 91精品国产综合久久久亚洲 | 色综合久 | 伊人精品在线视频 | 欧美一区二区三区久久精品视 | 亚洲色片网站 | 成人二区 | 蜜臀网 | 99久久精品免费看国产高清 | 国产一区欧美 |