// thirdPart.go 文件 func GetSource1() { // 堆代码 duidaima.com // do something } func GetSource2() { // do something } // 使用 func main() { result1: = GetSource1() result2: = GetSource2(); }直接使用的函数的函数也是可以的,只是没有设计,在后续的扩展时候就会发现很多问题:
// 定义数据源获取接口, type IDataSource interface { FetchData()([]byte, error) } // 数据源实体1 type Source1 struct{} func (s *Source1)FetchData()([]byte, error){ // do somnething return result,err } // 数据源实体2 type Source2 struct{} func (s *Source1)FetchData()([]byte, error){ // do somnething return result,err } // 工厂类 type Factory struct{} func (F factory)NewFactory(key string) *IDataSource { switch key { case "source1": return &Source1{} case "source2": return &Source2{} } } // main.go func main(){ s := NewFactory("source1") s.FetchData() }可以从上面简单的代码例子可以看到:
type SourceParams struct { Start string UserId string } type Source1 struct { } func (*Source1) FetchData(params interface{}) ([]byte, error) { p := params.(SourceParams) // do something ... }相同数据源不同获取方式
type Factory struct{} func (F factory)NewFactory(key string) *IDataSource { switch key { case "source1": return &Source1{} case "source1V1": return &source1V1{} case "source2": return &Source2{} } }第二版本:使用策略模式
type FetchStrategy interface{ Fetch()([]byte,error) } // 获取数据方式1 type FetchV1 struct{} func (s *FetchV1) Fetch() { // do something ... } // 获取数据方式2 type FetchV2 struct{} func (s *FetchV2) Fetch() { // do something ... } type Source1 struct { strategy FetchStrategy // 数据源增加strategy 属性 } // 获取时就可以根据对应策略获取数据 func (s *Source1) FetchData(params interface{}) ([]byte, error) { p := params.(SourceParams) // do something ... s.strategy.Fetch() } // 外层的工厂模式中返回对应的实体时可以增加对应策略key参数 func (F factory)NewFactory(key string, strategy FetchStrategy) *IDataSource { switch key { case "source1": return &Source1{strategy:strategy} case "source2": return &Source2{} } }
从上面的源码可以看到,在Souce中增加strategy 属性,在工厂中创建DataSource时,传入不同的策略对象到strategy字段中,这样就可以动态改变所使用的策略。在DataSource的FetchData方法内,它只需要调用strategy.Fetch()来触发对应的策略行为,而不需要关心具体是哪种策略。使用策略模式,可以灵活的切换不同的算法,后续有不同的获取的方式,只需要增加策略即可。当然使用策略模式应该还需要考虑下是不是需要使用。