假设你有一个服务类,它依赖于两个数据库存储库类。这就要求你在服务结构中存储这两个类。这对于少量的依赖关系来说是可以的,但如果你需要更多的依赖关系,你就会有一个大的结构和混乱的代码来处理。你可能会让其他的服务做同样的事情,但是为不同的资源库类。最后,你会有很多重复的东西在那里。解决这个问题的方法很简单。我们将创建一个主资源库结构,将所有其他/子资源库的接口存储在其中。我们只需在我们需要的地方使用主资源库。这将使我们能够访问所有的嵌入式资源库。这有点像策略模式。
结构
├── cmd
│ └── client
│ └── main.go
└── internal
├── dao
│ ├── article.go
│ └── label.go
├── repository
│ ├── article.go
│ ├── label.go
│ └── repository.go
└── service
├── article.go
└── label.go
文件
dao/article.go
package dao
import "time"
type ArticleRepository interface {
Insert(article *Article) error
Find(ID string) (*Article, error)
}
type Article struct {
ID string
Title string
PublishedAt time.Time
}
dao/label.go
package dao
type LabelRepository interface {
Insert(label *Label) error
List(limit uint8) ([]*Label, error)
}
type Label struct {
ID string
Name string
}
repository/repository.go
package repository
import "github.com/you/client/internal/dao"
type Repository struct {
Article dao.ArticleRepository
Label dao.LabelRepository
}
func New() Repository {
return Repository{
Article: article{},
Label: label{},
}
}
存储库/文章.go
package repository
import (
"log"
"github.com/you/client/internal/dao"
)
type article struct{}
func (a article) Insert(article *dao.Article) error {
log.Println("inserting article")
return nil
}
func (a article) Find(ID string) (*dao.Article, error) {
log.Println("finding article")
return nil, nil
}
仓库/标签.go
package repository
import (
"log"
"github.com/you/client/internal/dao"
)
type label struct{}
func (l label) Insert(label *dao.Label) error {
log.Println("inserting label")
return nil
}
func (l label) List(limit uint8) ([]*dao.Label, error) {
log.Println("listing labels")
return nil, nil
}
service/article.go
package service
import (
"github.com/you/client/internal/dao"
"github.com/you/client/internal/repository"
)
type Article struct {
repo repository.Repository
}
func NewArticle(repo repository.Repository) Article {
return Article{repo: repo}
}
func (a Article) DoSomething() {
_ = a.repo.Article.Insert(&dao.Article{})
_, _ = a.repo.Article.Find("id")
}
服务/label.go
package service
import (
"github.com/you/client/internal/dao"
"github.com/you/client/internal/repository"
)
type Label struct {
repo repository.Repository
}
func NewLabel(repo repository.Repository) Label {
return Label{repo: repo}
}
func (l Label) DoSomething() {
_ = l.repo.Label.Insert(&dao.Label{})
_, _ = l.repo.Label.List(1)
}
main.go
package main
import (
"github.com/you/client/internal/repository"
"github.com/you/client/internal/service"
)
func main() {
repo := repository.New()
articleService := service.NewArticle(repo)
articleService.DoSomething()
labelService := service.NewLabel(repo)
labelService.DoSomething()
}
测试
$ go run -race cmd/client/main.go
2020/12/22 23:26:14 inserting article
2020/12/22 23:26:14 finding article
2020/12/22 23:26:14 inserting label
2020/12/22 23:26:14 listing labels