關(guān)于Golang面試寶典
最近幾年叠殷,Go的熱度持續(xù)飆升,國內(nèi)外很多大公司都在大規(guī)模的使用Go揖庄。Google是Go語言誕生的地方栗菜,其他公司如Facebook、騰訊蹄梢、阿里疙筹、字節(jié)跳動、百度禁炒、京東而咆、小米等都在擁抱和轉(zhuǎn)向Go。Go語言的開源項(xiàng)目也非常多幕袱,如kubernetes暴备、docker、etcd们豌。
隨著市場對Go語言人才需求的增長涯捻,很多開發(fā)者都投入了Go語言的懷抱。本系列文章將以第一視角與大家一同開始Golang的面試之路望迎,希望大家能夠有所收獲障癌,拿下心儀的offer。
使用Go實(shí)現(xiàn)23種設(shè)計(jì)模式——行為型模式(下)
訪問者模式
在不改變各元素的類的前提下定義作用于這些元素的新操作
適用場景
- 數(shù)據(jù)結(jié)構(gòu)相對穩(wěn)定的對象辩尊,且需要經(jīng)常在此結(jié)構(gòu)上定義新操作
Go語言實(shí)現(xiàn)
type Number struct {
Numbers []int
}
func (n *Number) Do(v IVisitor) {
v.Do(n.Numbers)
}
type IVisitor interface {
Do([]int)
}
type AddVisitor struct{}
func (v *AddVisitor) Do(numbers []int) {
sum := 0
for _, n := range numbers {
sum += n
}
fmt.Printf("sum: %d\n", sum)
}
type TimesVisitor struct{}
func (v *TimesVisitor) Do(numbers []int) {
res := 1
for _, n := range numbers {
res *= n
}
fmt.Printf("res: %d\n", res)
}
func main() {
a := Number{Numbers: []int{1, 2, 3, 4}}
a.Do(&AddVisitor{})
a.Do(&TimesVisitor{})
}
訪問者模式優(yōu)點(diǎn)
- 增加新的操作簡單
訪問者模式缺點(diǎn)
- 增加新的數(shù)據(jù)結(jié)構(gòu)困難
模板方法模式
定義一個操作中的算法的骨架涛浙,而將一些步驟延遲到子類中,使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟
適用場景
- 模板模式解決了一些方法通用对省,卻在每個子類都重新寫一遍的這些方法
Go語言實(shí)現(xiàn)
type Notify struct {
}
func (n *Notify) Send() {
fmt.Println("send error")
}
type SMSNotify struct {
Notify
}
func (n *SMSNotify) Send() {
fmt.Println("send sms success")
}
type EMailNotify struct {
Notify
}
func (n *EMailNotify) Send() {
fmt.Println("send email success")
}
func main() {
a := SMSNotify{}
a.Send()
b := EMailNotify{}
b.Send()
}
模板方法模式優(yōu)點(diǎn)
- 封裝不變的部分蝗拿,擴(kuò)展可變部分
- 提取公共代碼,便于維護(hù)
- 行為由父類控制蒿涎,子類實(shí)現(xiàn)
模板方法模式缺點(diǎn)
- 每一個不同的實(shí)例哀托,都需要一個子類來實(shí)現(xiàn),導(dǎo)致類的個數(shù)增加
策略模式
定義一系列的算法劳秋,把它們一個個封裝起來仓手,并且使它們可相互替換
適用場景
- 一個類定義了多種行為,并且這些行為以多個if...else形式出現(xiàn)
Go語言實(shí)現(xiàn)
type Operation interface {
Do(n1, n2 int) int
}
type OperationAdd struct {
}
func NewOperationAdd() *OperationAdd {
return &OperationAdd{}
}
func (o *OperationAdd) Do(n1, n2 int) int {
return n1 + n2
}
type OperationSubtract struct {
}
func NewOperationSubtract() *OperationSubtract {
return &OperationSubtract{}
}
func (o *OperationSubtract) Do(n1, n2 int) int {
return n1 -n2
}
type Context struct {
operation Operation
}
func NewContext(operation Operation) *Context {
return &Context{operation: operation}
}
func (c *Context) Do(n1, n2 int) int {
return c.operation.Do(n1, n2)
}
func main() {
a := NewContext(NewOperationAdd())
a.Do(1, 2)
b := NewContext(NewOperationSubtract())
b.Do(3, 1)
}
策略模式優(yōu)點(diǎn)
- 避免使用多重判斷語句
- 算法可自由切換
- 擴(kuò)展性好
策略模式缺點(diǎn)
- 客戶端需要理解所有策略算法的區(qū)別玻淑,以便選擇合適的算法類
- 策略類很多嗽冒,增加維護(hù)難度
狀態(tài)模式
允許一個對象在其內(nèi)部狀態(tài)改變時改變它的行為
適用場景
- 代碼中包含大量與對象狀態(tài)有關(guān)的條件語句
Go語言實(shí)現(xiàn)
type Account struct {
Action State
status string
}
func NewAccount(status string) *Account {
a := &Account{status: status}
a.initState()
return a
}
func (a *Account) initState() {
if a.status == "normal" {
a.Action = &NormalState{}
} else {
a.Action = &BannedState{}
}
}
type State interface {
Login()
}
type NormalState struct{}
func (s *NormalState) Login() {
fmt.Println("登陸成功")
}
type BannedState struct{}
func (s *BannedState) Login() {
fmt.Println("賬號封禁,禁止登陸")
}
func main() {
a := NewAccount("normal")
a.Action.Login()
}
狀態(tài)模式優(yōu)點(diǎn)
- 封裝了轉(zhuǎn)換規(guī)則
- 將所有與狀態(tài)相關(guān)的行為放到一個類中补履,方便的增加狀態(tài)
- 允許狀態(tài)轉(zhuǎn)換邏輯和狀態(tài)對象合成一體添坊,而不是巨大的條件語句塊
狀態(tài)模式缺點(diǎn)
- 增加了系統(tǒng)中類和對象的個數(shù),導(dǎo)致系統(tǒng)運(yùn)行開銷變大
- 狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)都比較復(fù)雜
- 對"開閉原則"的支持不友好