JOJO 是 CPU 大学 CS 专业的一名学生。在入学时,JOJO 了解到这个学校有一些很奇怪的规则:
- 学生必须获得所有课程的学分才能毕业。
- 学生必须在报名并修完一门课程才能学习其他课程。
- 如果一门课程(后简称 课程 A)存在前置课程,并且此时没有获得前置课程的学分时,【课程 A】 教学中将自动添加所有前置课程的内容。
- 在第三条情况下完成的课程,仍然只获得此课程的学分。
“这 ** 不是坑爹呢?!”JOJO 想。“前置课程没学,教学中把前置课程的内容讲一遍倒是很合理,但是这第四条又说只给这门课的学分,那如果我排序错乱,岂不是一门课得学好几遍?”
CS 专业有三门课,C 语言(以下简称 C )、计算机组成原理(CCP)以及操作系统(OS)。其中:
- C 不需要前置课程
- CCP 依赖 C
- OS 依赖 C 和 CCP
JOJO 想,“很显然,想要不重复学习一门课程,就需要保证在学习某一门课程时,所有前置课程的学分我都拿到了。因而,很容易想到如下的简单算法。”
interface ICourse {
name: string;
preCourses: ICourse[];
}
type jojosBizarreAlgorithm = (course: ICourse) => void
const jojosBizarreAlgorithm: jojosBizarreAlgorithm = course => {
course.preCourses.forEach(jojosBizarreAlgorithm)
learnCourse(new Course(course.name))
}
const unfinishedCourses = OAA.getAllUnfinishedCourses()
while (unfinishedCourses.length) {
const courseOfMostInterest = getMostInterestCourse(unfinishedCourses)
jojosBizarreAlgorithm(courseOfMostInterest)
}
复制代码
回到依赖注入
JOJO 用这个算法顺利且省事的毕业了。让我们回到依赖注入这个点上。
让我们看以下的代码,实际上做的就是第三条和第四条规则所做的事情:如果在没有学习 C 和 CCP 的情况下,new 一个 OS 服务需要创建其依赖的 C 和 CCP。但是由于 C 和 CCP 都是在 OS 的构造函数内构造的,所以外部无法获得二者,仍然需要重新构造。
class Course {
constructor(name: string) {
// 构造需要的服务
getAllPreCourses(name).forEach(
preCourseName => new Course(preCourseName))
// 自身的逻辑
learn(name)
}
}
new Course('os')
复制代码
在三个服务存在依赖的情况下就已经会出现如此多重复 new 服务的情况了。更不要说更加复杂的项目,几十个服务互相关联,想想都是灾难性的。依赖注入很重要的一个目的就是减少这种无意义的构造,每个课程不用去关注学习前置课程(构造依赖的服务),只需要考虑自己课程的学习(自身服务逻辑的编写)就可以了。
当然,在具体的开发中可没有人会手动向 course.preCourses 这样的数组中添加依赖,本文只是屏蔽了如何获得依赖的实现细节。如果想了解此部分,请耐心等待本文下一部分的内容。?
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END