Reference: DI Wiki, DIP,YouTuBe, YouTuBe, Blog, Blog
What
What is dependency injection, the literal meaning is Inject the dependencies.
What is Dependency?
The Dependency is other object that your class need functional.
What is Injection?
Injection means you pushed the dependency into your class.
- Recommend: push dependency as parameter or use setter method;
- Not Recommend: new dependency in your class;
In the wiki introduction, the Dependency injection involves four roles, which i will use it to explain the DI concept;
1 | - the **service** objects to be used |
Why
The reason why DI is important? DIP dependency inversion principle;
Example
The above description is too abstract to understand; In one word, DI is a kind of design mode:
1 | The intent behind dependency injection is to achieve separation of concerns of construction and use of objects. This can increase readability and code reuse. |
Here is a scenario, a server API would use DB model to get some information;
Bad programming style
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15type Service struct {
// some fields definition
}
func (s *Service)GetData(id string) string{
db := new(mysql)
return db.queryData(id)
}
func NewService() *Service{
return &Service{}
}
service := NewService()
service.Run()After Dependency Injection
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15type Service struct {
// some fields definition
db *MYSQLClient
}
func (s *Service)GetData(id string) string{
return s.db.queryData(id)
}
func NewService() *Service{
return &Service{db: NewMySQLClient(mySqlUrl)}
}
service := NewService("mysql://url")
service.Run()After Dependency Inversion Principle
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46type DataSource interface {
GetDataById(id string) string
}
type mySql struct {
m *MySqlClient
}
func (m *mysql) GetDataById(id string) string {
return m.m.Exec("select data from table where id = ?", id)
}
func NewMySQL(addr string) *mySql {
return &mySql{m: NewMySQLClient(addr)}
}
type redis struct {
r *RedisClient
}
func (r *RedisClient) GetDataById(id string) string {
return r.r.Do("GET", "table_"+id)
}
func NewRedis(addr string) *redis {
return &redis{r: NewRedisClient(addr)}
}
type Service struct {
// some fields definition
db DataSource
}
func (s *Service)GetData(id string) string{
return s.db.GetDataById(id)
}
func NewService(addr string) *Service{
// Redis
return &Service{db: NewRedis(myRedisUrl)}
// Mysql
return &Service{db: NewMySQL(myRedisUrl)}
}
service := NewService()
service.Run()