清晰架构(Clean Architecture)的Go微服务: 依赖注入(Dependency Injection)

在清晰架构(Clean Architecture)中,应用程序的每一层(用例,数据服务和域模型)仅依赖于其他层的接口而不是具体类型。 在运行时,程序容器¹负责创建具体类型并将它们注入到每个函数中,它使用的技术称为依赖注入²。 以下是要求。

容器包的依赖关系:

  1. 容器包是唯一依赖于具体类型和许多外部库的包,因为它需要创建具体类型。 本程序中的所有其他软件包主要仅依赖于接口。

  2. 外部库可以包括DB和DB连接,gRPC连接,HTTP连接,SMTP服务器,MQ等。

  3. #2中提到的具体类型的资源链接只需要创建一次并放入注册表中,所有后来的请求都将从注册表中检索它们。

  4. 只有用例层需要访问并依赖于容器包。

依赖注入的核心是工厂方法模式(factory method pattern)。

工厂方法模式(Factory Method Pattern):

实现工厂方法模式并不困难,这里³描述了是如何在Go中实现它的。困难的部分是使其可扩展,即如何避免在添加新工厂时修改代码。

处理新工厂的方式有很多种,下面是常见的三种:

#1不是一个好选择,因为你需要在添加新类型时修改现有代码。 #3是最好的,因为添加新工厂时现有代码不需更改。在Java中,我会使用#3,因为Java具有非常优雅的反射实现。你可以执行类似“(Animal)Class.forName(”className“)。newInstance()”的操作,即你可以将类的名称作为函数中的字符串参数传递进来,并通过反射从中创建一个类型的新实例,然后将结构转换为适当的类型(可能是它的一个超级类型(super type),这是非常强大的。由于Go的反射不如Java,#3不是一个好选择。在Go中,由反射创建的实例是反射类型而不是实际类型,并且你无法在反射类型和实际类型之间转换类型,它们处于两个不同的世界中,这使得Go中的反射难以使用。所以我选择#2,它比#1好,但是在添加新类型时需要更改少部分代码。

以下是数据存储工厂的代码。它有一个“dsFbInterface”,其中有一个“Build”函数需要由每个数据存储工厂实现。 “Build”是工厂的关键部分。 “dsFbMap”是每个数据库(或gRPC)的代码(code)与实际工厂之间的映射。这是添加数据库时需要更改的部分。


// To map "database code" to "database interface builder"
// Concreate builder is in corresponding factory file. For example, "sqlFactory" is in "sqlFactory".go
var dsFbMap = map[string]dsFbInterface{
   
	config.SQLDB:      &sqlFactory{
   },
	config.COUCHDB:    &couchdbFactory{
   },
	config.CACHE_GRPC: &cacheGrpcFactory{
   },
}

// DataStoreInterface serve as a marker to indicate the return type for Build method
type DataStoreInterface interface{
   }

// The builder interface for factory method pattern
// Every factory needs to implement Build method
type dsFbInterface interface {
   
	Build(container.Container, *config.DataStoreConfig) (DataStoreInterface, error)
}

//GetDataStoreFb is accessors for factoryBuilderMap
func GetDataStoreFb(key string) dsFbInterface {
   
	return dsFbMap[key]
}

以下是“sqlFactory”的程序,它实现了上面的代码中定义的“dsFbInterface”。 它为MySql数据库创建数据存储。 在“Build”函数中,它首先从注册表中检索数据存储(MySql),如果找到,则返回,否则创建一个新的并将其放入注册表。
因为注册表可以存储任何类型的数据,所以我们需要在检索后将返回值转换为适当的类型(*sql.DB)。 “databasehandler.SqlDBTx”是实现“SqlGdbc”接口的具体类型。 它的创建是为了支持事务管理。 代码中调用“sql.Open()”来打开数据库连接,但它并没有真正执行任何连接数据库的操作。 因此,需调用“db.Ping()”去访问数据库以确保数据库正在运行。


// sqlFactory is receiver for Build method
type sqlFactory struct{
   }

// implement Build method for SQL database
func (sf *sqlFactory) Build(c container.Container, dsc *config.DataStoreConfig) (DataStoreInterface, error) 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值