主页

索引

模块索引

搜索页面

Abstract Factory-抽象工厂

备注

工厂模式用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。

简单工厂模式

示例:

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,
  }
}

抽象工厂模式

备注

groups object factories that have a common theme. 和简单工厂模式的唯一区别,就是它返回的是接口而不是结构体。

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)
  }
}

主页

索引

模块索引

搜索页面