Abstract Factory-抽象工厂 ######################### .. note:: 工厂模式用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。 简单工厂模式 ============ 示例:: type Person struct { Name string Age int } func (p Person) Greet() { fmt.Printf("Hi! My name is %s", p.Name) } 简单工厂模式是最常用、最简单的。它就是一个接受一些参数,然后返回 Person 实例的函数:: func NewPerson(name string, age int) *Person { return &Person{ Name: name, Age: age, } } 抽象工厂模式 ============ .. note:: groups object factories that have a common theme. 和简单工厂模式的唯一区别,就是它返回的是接口而不是结构体。 .. image:: https://img.zhaoweiguo.com/knowledge/images/architectures/design-modes/Creationals/abstract-factory1.png 通过返回接口,可以在你不公开内部实现的情况下,让调用者使用你提供的各种功能:: type Person interface { Greet() } // Here, NewPerson returns an interface, and not the person struct itself func NewPerson(name string, age int) Person { return person{ name: name, age: age, } } 通过返回接口,我们还可以实现多个工厂函数,来返回不同的接口实现:: // We define a Doer interface, that has the method signature // of the `http.Client` structs `Do` method type Doer interface { Do(req *http.Request) (*http.Response, error) } // This gives us a regular HTTP client from the `net/http` package func NewHTTPClient() Doer { return &http.Client{} } type mockHTTPClient struct{} func (*mockHTTPClient) Do(req *http.Request) (*http.Response, error) { // The `NewRecorder` method of the httptest package gives us // a new mock request generator res := httptest.NewRecorder() // calling the `Result` method gives us // the default empty *http.Response object return res.Result(), nil } // This gives us a mock HTTP client, which returns // an empty response for any request sent to it func NewMockHTTPClient() Doer { return &mockHTTPClient{} } 要测试的实例:: func QueryUser(doer Doer) error { req, err := http.NewRequest("Get", "http://api.zhaoweiguo.com/v1/secrets", nil) if err != nil { return req } _, err := doer.Do(req) if err != nil { return err } return nil } 其测试用例为:: func TestQueryUser(t *testing.T) { doer := NewMockHTTPClient() if err := QueryUser(doer); err != nil { t.Errorf("QueryUser failed, err: %v", err) } }