İki tane veritabanı repository sınıfına bağlı olan bir servisinizin olduğunu varsayın. Bu durumda her ikisini de servis yapısında saklarsınız. Bu, az miktarda bağımlılık için uygundur, ancak daha fazla dependency injection yapısı varsa, çalışabileceğiniz büyük bir yapıya ve dağınık bir koda sahip olursunuz. Aynı şeyi farklı repository sınıfları için yapan başka servislere de sahip olabilirsiniz. Sonunda her yerde bir sürü kopya kod oluşabilir. Bu sorunun çözümü basittir. Tüm alt repository sınıf arayüzlerini içinde saklayacak bir ana yapı oluşturacağız. İhtiyaç duyduğumuz yerde sadece ana depoyu kullanacağız. Bu, tüm gömülü repository sınıflarına ondan erişmemizi sağlayacaktır. Biraz strateji modeli gibi.


Yapı


├── cmd
│   └── client
│   └── main.go
└── internal
├── dao
│   ├── article.go
│   └── label.go
├── repository
│   ├── article.go
│   ├── label.go
│   └── repository.go
└── service
├── article.go
└── label.go

Dosyalar


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

repository/acticle.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
}

repository/label.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")
}

service/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()
}

Test


$ 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