手撸golang 架构设计原则 依赖倒置原则

Posted ioly

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手撸golang 架构设计原则 依赖倒置原则相关的知识,希望对你有一定的参考价值。

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

以上是关于手撸golang 架构设计原则 依赖倒置原则的主要内容,如果未能解决你的问题,请参考以下文章

手撸golang 架构设计原则 合成复用原则

手撸golang 架构设计原则 单一职责原则

手撸golang 架构设计原则 里氏替换原则

手撸golang 架构设计原则 开闭原则

手撸golang 架构设计原则 迪米特法则

云原生一篇打通架构设计,Java设计模式6,依赖倒置原则