golang 架构设计准则 依赖倒置准则
缘起
最近温习设计模式
拜读谭勇德的 << 设计模式就该这样学 >>
该书以 java 语言演绎了常见设计模式
本系列笔记拟采纳 golang 练习之
依赖倒置准则
- 依赖倒置准则(Dependence Inversion Principle, DIP)指设计代码构造时,高层模块不应该依赖底层模块,二者都应该依赖其形象。
- 形象不应该依赖细节,细节应该依赖形象。
- 常见的依赖注入形式有: 办法参数注入, 结构器参数注入, setter 办法注入
_
场景
- 线上学校有一系列课程
- 用户可抉择若干门课程进行学习
- 如果把学习课程的过程间接实现为用户的办法, 则每减少一门课程, 就须要减少一个学习办法
- 依据依赖倒置准则, 能够把学习过程形象为学习接口, 由不同的课程实例各自实现
BadUser.go
BadUser 以不同办法实现各种课程的学习过程, 课程的减少导致 BadUser 代码越来越臃肿
package dependence_inversion
import "fmt"
type BadUser struct {
iID int
sName string
}
func NewBadUser(id int, name string) *BadUser {
return &BadUser{
iID: id,
sName: name,
}
}
func (me *BadUser) StudyJavaCourse() {fmt.Printf("%v is learning %v\n", me.sName, "java")
}
func (me *BadUser) StudyGolangCourse() {fmt.Printf("%v is learning %v\n", me.sName, "golang")
}
GoodUser.go
GoodUser 通过实现 IUser 接口提供用户根本信息, 并把不同课程的学习过程, 委托给 ICourse 接口去实现
package dependence_inversion
type IUser interface {ID() int
Name() string
Study(ICourse)
}
type GoodUser struct {
iID int
sName string
}
func NewGoodUser(id int, name string) IUser {
return &GoodUser{
iID: id,
sName: name,
}
}
func (me *GoodUser) ID() int {return me.iID}
func (me *GoodUser) Name() string {return me.sName}
func (me *GoodUser) Study(course ICourse) {course.SetUser(me)
course.Study()}
GolangCourse.go
通过 setter 办法注入 IUser, ICourse 接口封装了具体课程的学习过程
package dependence_inversion
import "fmt"
type ICourse interface {ID() int
Name() string
SetUser(IUser)
Study()}
type GolangCourse struct {
iID int
sName string
xCurrentUser IUser
}
func NewGolangCourse() ICourse {
return &GolangCourse{
iID: 11,
sName: "golang",
xCurrentUser: nil,
}
}
func (me *GolangCourse) ID() int {return me.iID}
func (me *GolangCourse) Name() string {return me.sName}
func (me *GolangCourse) SetUser(user IUser) {me.xCurrentUser = user}
func (me *GolangCourse) Study() {fmt.Printf("%v is learning %v\n", me.xCurrentUser.Name(), me.Name())
}
dependence_inversion_test.go
测试用例
package main
import "testing"
import (dip "learning/gooop/principles/dependence_inversion")
func TestDIP(t *testing.T) {bu := dip.NewBadUser(1, "Tom")
bu.StudyGolangCourse()
gu := dip.NewGoodUser(2, "Mike")
gu.Study(dip.NewGolangCourse())
}
测试输入
$ go test -v main/dependence_inversion_test.go
=== RUN TestDIP
Tom is learning golang
Mike is learning golang
--- PASS: TestDIP (0.00s)
PASS
ok command-line-arguments 0.002s