理论
定义
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),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。
网友评论