架构师训练营 -02 作业
作业一:
请描述什么是依赖倒置原则,为什么有时候依赖倒置原则又被称为好莱坞原则?
作业二:
请描述一个你熟悉的框架,是如何实现依赖倒置原则的。
作业三:
请用接口隔离原则优化 Cache 类的设计,画出优化后的类图。
作业一答:
面对高层模块依赖底层模块的分层依赖的问题:
维护困难
复用困难
DIP(依赖倒置原则):指一种特定的解耦形式,使得高层次的模块不依赖于低层次的模块的实现细节,依赖关系被颠倒(反转),从而使得低层次模块依赖于高层次模块的需求抽象。
核心:面向抽象(抽象类或接口)编程(Object-Oriented Design, OOD),关键是接口所有权的倒置。
依赖倒置原则的包含如下的三层含义:
高层模块不应该依赖低层模块,两者都应该依赖其抽象
抽象不应该依赖实现
实现应该依赖抽象
每一个逻辑的实现都是由原子逻辑组成的,不可分割的原子逻辑就是低层模块(一般是接口,抽象类),原子逻辑的组装就是高层模块。抽象就是指接口和或抽象类,两者都不能被直接实例化。细节就是实现类,实现接口或继承抽象类而产生的类就是细节,可以被直接实例化。
具体理解为:
1、模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的
2、接口或抽象类不依赖于实现类
3、实现类依赖于接口或抽象类
解决的实质问题:通过抽象(抽象类或接口)使各个类或模块实现彼此独立,不互相影响,实现模块间的松耦合。
所以在开发过程中要遵循以下原则;
每个类尽量都要有接口或抽象类,或者抽象类和接口都有: 依赖倒置原则的基本要求,有抽象才能依赖倒置
变量的表面类型尽量是接口或者抽象类
任何类都不应该从具体类派生
尽量不要重写基类已经写好的方法(里式替换原则)
DIP的好处: 采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。
好莱坞原则(Hollywood Principle):不要调用我,让我来调用你。
作用:防止“依赖腐败”
解释:在好莱坞原则之下,我们允许低层组件将自己挂钩到系统上,但是高层组件会决定什么时候和怎样使用这些低层组件。换句话说,高层组件对待低层组件的方式是“别调用我们,我们会调用你”
好莱坞原则和依赖倒置原则之间关系如何?
依赖倒置原则教我们尽量避免使用具体类,而多使用抽象。
而好莱坞原则是用在创建框架或组件上的一种技巧,好让低层组件能够被挂钩进计算中,而且又不会让高层组件依赖低层组件。两这个的目标都是在于解耦,但是依赖倒置原则更加注重如何在设计中避免依赖。
好莱坞原则教我们一个技巧,创建一个有弹性的设计,允许低层结构能够互相操作,而又防止其他类太过依赖它们。
无论依赖倒置原则还是好莱坞原则体现的高层次(类或组件)与低层次(类或组件)的关系,本质目的是一样的就是解耦,都是针对的是面向接口编程,体现的是接口隔离。
作业二答:
举例:
springboot的监控检查的设计2.1.7版本,任何中间件或数据库对接口HealthIndicator的实现都可以被springboot的actuator自动调用,完成健康状态的检查。
主要分A和B两个过程,A过程主要是完成对所需要的bean的装配,由上游决定哪些组件或实现HealthIndicator接口的可以进行健康检查;B主要是调用过程返回结果。
A、项目启动完成对bean的自动装配过程
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
前提是加入上面的依赖。
首先,如上图springBootCondition类完成对配置文件的读取是否启用健康检查等。入口为maches方法。子类重写getMatchOutCome实现。
其次,每个XXXHealthIndicatorAutoConfiguration都有HealthIndicatorAutoConfiguration注解(@AutoConfigureBefore(HealthIndicatorAutoConfiguration.class))对HealthAggregator和HealthIndicatorRegistry的实例化。
其中对HealthIndicatorRegistry实例化由HealthIndicatorRegistryBeans来完成,如下图。
由applicationContext获取所有实现HealthIndicator接口的类,由工厂类HealthIndicatorRegistryFactory完成对HealthIndicatorRegistry的创建。我们自己实现的HealthIndicator类也是在这完成注册的。
再次,如上图,每个XXXHealthIndicatorAutoConfiguration都有一个父类CompositeHealthIndicatorConfiguration,注入了一个healthAggregator 和由DefaultHealthIndicatorRegistry类实现注册, 最终由类CompositeHealthIndicator 完成对该健康检查的实例,完成对boot实现的类的注册。
B、当请求的时候是如何处理的?
1、准备,先看一个关系图。
HealthEndpointAutoConfiguration 中引入配置HealthEndpointConfiguration ,在这个配置中实例化HealthEndpoint
可见是由CompositeHealthIndicator类具体来完成,而该类是由HealthAggregator和HealthIndicatorRegistry来完成。
这2个类在第一步中已经完成对bean的装配。
2、调用请求:http://ip:port/actuator/health
最后执行health方法就是HealthIndicator的实现类CompositeHealthIndicator的health方法,具体见下图。完成对所有实现HealthIndicator接口的registry注册过的health检查,并最后有HealthAggregator聚合类实现排序返回结果。
作业三答:
说明:
1、对外暴露ICache接口,供调用方使用。
2、类Build通过组合接口用ICacheBuid完成对配置的构建。
评论