缘起
最近复习设计模式
拜读谭勇德的<<设计模式就该这样学>>
该书以java语言演绎了常见设计模式
本系列笔记拟采用golang练习之
依赖倒置原则
- 依赖倒置原则(Dependence Inversion Principle, DIP)指设计代码结构时,高层模块不应该依赖底层模块,二者都应该依赖其抽象。
- 抽象不应该依赖细节,细节应该依赖抽象。
- 常见的依赖注入方式有: 方法参数注入, 构造器参数注入, setter方法注入
场景
- 线上学校有一系列课程
- 用户可选择若干门课程进行学习
- 如果把学习课程的过程直接实现为用户的方法, 则每增加一门课程, 就需要增加一个学习方法
- 根据依赖倒置原则, 可以把学习过程抽象为学习接口, 由不同的课程实例各自实现
BadUser.go
不好的示例: BadUser以不同方法实现各种课程的学习过程, 课程的增加导致BadUser代码越来越臃肿
package dependence_inversionimport "fmt"type BadUser struct {iID intsName 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_inversiontype IUser interface {ID() intName() stringStudy(ICourse)}type GoodUser struct {iID intsName 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_inversionimport "fmt"type ICourse interface {ID() intName() stringSetUser(IUser)Study()}type GolangCourse struct {iID intsName stringxCurrentUser 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 mainimport "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 TestDIPTom is learning golangMike is learning golang--- PASS: TestDIP (0.00s)PASSok command-line-arguments 0.002s
