理論
定義
Define a family of algorithms,encapsulate each one,and make them interchangeable.(定義一組算法,將每個算法封裝起來,并且使他們之間可以互換)
類圖
StrategyPattern.jpg
- Context的作用是承上啟下,屏蔽高層模塊對策略,算法的直接訪問,封裝可能存在的變化
- Strategy是策略的抽象,每一個具體的策略都需要具有按照Strategy的規范實現
- ConcreteStrategy各個策略的具體實現
實戰
場景
想要做一個基金的價格提醒功能,在基金的凈值從同類產品的均價之上下降到同類產品的均價之下后,發一個短信提示
為了完成上述功能,則勢必需要寫一個爬蟲,對基金每日的凈值進行抓取,為了保證每天的數據都可以正常的獲取到,則需要準備多個爬蟲腳本對不同的數據源進行抓取,每種數據源的爬蟲可以視作一個策略
Strategy
//定義如下的爬蟲接口
type fundCrawler interface {
check(fundCode string) (netWorth float64, err error)
crawler(fundCode string, startFrom time.Time) (netWorths []FundNetWorth, err error)
}
ConcreteStrategy
為了提供一個更加穩健的服務,選擇從天天基金,京東金融,螞蟻金服三個平臺獲取數據
這里只通過一個爬蟲來說明具體的策略的實現
type tiantianCrawler struct {
baseURL string
}
func (tiantianCrawler tiantianCrawler) crawler(fundCode string, startFrom time.Time) (netWorths []FundNetWorth, err error) {
netWorths, err = []FundNetWorth{FundNetWorth{time.Now(), 1.423}}, nil
return
}
func (tiantianCrawler tiantianCrawler) check(fundCode string) (netWorth float64, err error) {
netWorth, err = 1.989, nil
return
}
Context
//CrawlerContext is crawler Context
type CrawlerContext struct {
worker fundCrawler
}
//CreateCrawlerContext create a context
func CreateCrawlerContext(concreteCrawler fundCrawler) (context CrawlerContext, err error) {
context, err = CrawlerContext{worker: concreteCrawler}, nil
return
}
//Operate triger crawler
func (context CrawlerContext) Operate(fundCode string, startFrom time.Time) (netWorths []FundNetWorth, err error) {
netWorths, err = context.worker.crawler(fundCode, startFrom)
return
}
上層使用
func useDemo() {
tiantian := tiantianCrawler{baseURL: "http://fund.eastmoney.com"}
context, err := CreateCrawlerContext(tiantian)
if err != nil {
return
}
context.Operate("161725", time.Now())
}
存在的問題
- 所有的策略類都對需要對外暴露違反了迪米特法則
迪米特法則(Law of Demeter)又叫作最少知道原則(Least Knowledge Principle 簡寫LKP),就是說一個對象應當對其他對象有盡可能少的了解,不和陌生人說話。