当前位置:网站首页>"Inversion of Control" and "Dependency Inversion", can't you tell the difference?
"Inversion of Control" and "Dependency Inversion", can't you tell the difference?
2022-08-08 09:29:00 【InfoQ】
- 控制反转(IoC)是什么?「反转」到底反转了什么?
- Spring和IOC之间是什么关系?
- 依赖注入(DI)和依赖倒置原则(DIP)又是什么?
- IOC、DI和DIP有什么关系?
1. 控制反转(IoC)
1.1 一个典型案例
public class UserServiceTest {
public static boolean doTest() {
//此处编写自己的判断逻辑
return false;
}
public static void main(String[] args) {
if (doTest()) {
System.out.println("Test succeed.");
} else {
System.out.println("Test failed.");
}
}
}
main
public abstract class TestCase {
public void run() {
if (doTest()) {
System.out.println("Test succeed.");
} else {
System.out.println("Test failed.");
}
}
public abstract boolean doTest();
}
public class JunitApplication {
private static final List<TestCase> cases = new ArrayList();
public static void register(TestCase testCase){
cases.add(testCase);
}
public static void main(String[] args) {
for(TestCase testCase : cases){
testCase.run();
}
}
}
UserServiceTest
TestCase
doTest
public class UserServiceTestCase extends TestCase{
@Override
public boolean doTest() {
//此处编写自己的判断逻辑
return false;
}
}
//注册测试用例
JunitApplication.register();
main
1.2 IoC概念的提出
inversion of control

1.3 为什么提出IoC

class A{
Object b = new B();
...
}
class B{
Object c = new C();
Object d = new D();
...
}
class C{
Object d = new D();
}
A
B



Servlet
Servlet
// 方式1
private MySQLDao dao = new MySQLDaoImpl();
// 方式2
private MySQLDao dao = (MySQLDao) BeanFactory.getBean("mySQLDao");
dao
dao
MySQLDaoImpl
mySQLDao
1.4 Spring和IoC的关系
1.5 面试中被问到IoC怎么回答
2. 依赖注入(DI)
2.1 定义
new()
Controller
Service
@Api(tags = {"报警联系人接口"})
@RestController
@RequestMapping("/iot/contact")
public class AlarmContactController extends BaseController {
// 这就是大名鼎鼎的DI啊,是不是非常简单!
@Autowired
private IAlarmContactService alarmContactService;
...
}
2.2 面试中被问到「依赖注入」怎么回答
3. 依赖倒置原则(DIP)
3.1 定义
- 高层模块(high-level modules)不要直接依赖低层模块(low-level);
- 高层模块和低层模块应该通过抽象(abstractions)来互相依赖;
- 抽象(abstractions)不要依赖具体实现细节(details),具体实现细节(details)依赖抽象(abstractions).
3.2 代码示例
/**
* @author 蝉沐风
* @desc 福特汽车厂商提供的接口
*/
public class FordCar{
public void run(){
System.out.println("福特开始启动了");
}
public void turn(){
System.out.println("福特开始转弯了");
}
public void stop(){
System.out.println("福特开始停车了");
}
}
/**
* @author【蝉沐风】
* @desc 本田汽车厂商提供的接口
*/
public class HondaCar {
public void run() {
System.out.println("本田开始启动了");
}
public void turn() {
System.out.println("本田开始转弯了");
}
public void stop() {
System.out.println("本田开始停车了");
}
}
/**
* @author【蝉沐风】
* @desc 自动驾驶系统
*/
public class AutoDriver {
public enum CarType {
Ford, Honda
}
private CarType type;
private HondaCar hcar = new HondaCar();
private FordCar fcar = new FordCar();
public AutoDriver(CarType type) {
this.type = type;
}
public void runCar() {
if (type == CarType.Ford) {
fcar.run();
} else {
hcar.run();
}
}
public void turnCar() {
if (type == CarType.Ford) {
fcar.turn();
} else {
hcar.turn();
}
}
public void stopCar() {
if (type == CarType.Ford) {
fcar.stop();
} else {
hcar.stop();
}
}
}
/**
* @author【蝉沐风】
* @desc 自动驾驶系统
*/
public class AutoDriver {
public enum CarType {
Ford, Honda, Audi, Benz, Bmw
}
private CarType type;
private HondaCar hcar = new HondaCar();
private FordCar fcar = new FordCar();
private AudiCar audicar = new AudiCar();
private BenzCar benzcar = new BenzCar();
private BmwCar bmwcar = new BmwCar();
public AutoDriver(CarType type) {
this.type = type;
}
public void runCar() {
if (type == CarType.Ford) {
fcar.run();
} else if (type == CarType.Honda) {
hcar.run();
} else if (type == CarType.Audi) {
audicar.run();
} else if (type == CarType.Benz) {
benzcar.run();
} else {
bmwcar.run();
}
}
public void turnCar() {
if (type == CarType.Ford) {
fcar.turn();
} else if (type == CarType.Honda) {
hcar.turn();
} else if (type == CarType.Audi) {
audicar.turn();
} else if (type == CarType.Benz) {
benzcar.turn();
} else {
bmwcar.turn();
}
}
public void stopCar() {
if (type == CarType.Ford) {
fcar.stop();
} else if (type == CarType.Honda) {
hcar.stop();
} else if (type == CarType.Audi) {
audicar.stop();
} else if (type == CarType.Benz) {
benzcar.stop();
} else {
bmwcar.stop();
}
}
}
- 高层模块(high-level modules)不要直接依赖低层模块(low-level);
- 高层模块和低层模块应该通过抽象(abstractions)来互相依赖;
- 抽象(abstractions)不要依赖具体实现细节(details),具体实现细节(details)依赖抽象(abstractions).
AutoDriver
XXCar
AutoDriver
new

ICar
AutoDriver
ICar
/**
* @author【蝉沐风】
* @desc 汽车的抽象接口
*/
public interface ICar {
void run();
void turn();
void stop();
}
public class FordCar implements ICar{
@Override
public void run(){
System.out.println("福特开始启动了");
}
@Override
public void turn(){
System.out.println("福特开始转弯了");
}
@Override
public void stop(){
System.out.println("福特开始停车了");
}
}
public class HondaCar implements ICar{
@Override
public void run() {
System.out.println("本田开始启动了");
}
@Override
public void turn() {
System.out.println("本田开始转弯了");
}
@Override
public void stop() {
System.out.println("本田开始停车了");
}
}
public class AudiCar implements ICar{
@Override
public void run() {
System.out.println("奥迪开始启动了");
}
@Override
public void turn() {
System.out.println("奥迪开始转弯了");
}
@Override
public void stop() {
System.out.println("奥迪开始停车了");
}
}
public class BenzCar implements ICar{
@Override
public void run() {
System.out.println("奔驰开始启动了");
}
@Override
public void turn() {
System.out.println("奔驰开始转弯了");
}
@Override
public void stop() {
System.out.println("奔驰开始停车了");
}
}
public class BmwCar implements ICar {
@Override
public void run() {
System.out.println("宝马开始启动了");
}
@Override
public void turn() {
System.out.println("宝马开始转弯了");
}
@Override
public void stop() {
System.out.println("宝马开始停车了");
}
}
/**
* @author【蝉沐风】
* @desc 自动驾驶系统
*/
public class AutoDriver {
private ICar car;
public AutoDriver(ICar car) {
this.car = car;
}
public void runCar() {
car.run();
}
public void turnCar() {
car.turn();
}
public void stopCar() {
car.stop();
}
}
AutoDriver
ICar
XXXCar
AutoDriver
ICar
XXXCar
ICar
AutoDriver
ICar

AutoDriver
XXXCar
AutoDriver
ICar
XXXCar
ICar
3.3 无所不在的抽象
3.3.1 JVM的抽象
3.3.2 货币的诞生
边栏推荐
- Android Studio关于MainActivity中的“import kotlinx.android.synthetic.main.activity_main.*”出现错误提示
- Excel中text函数5中常用方法
- 【AGC】开放式测试示例
- mysql-cdc 换2.2.x 版本 怎么读不到 数据 咋回事
- VPP源地址NAT
- 机器学习理论及案例分析(part3)--聚类
- Why is HTTS safer?
- 【Collection】3. Wallpaper collection
- Using classification weights, it is easy to solve the problem of data imbalance
- 软件测试的分类
猜你喜欢
攻防世界——ics-05
67:第五章:开发admin管理服务:20:开发【解冻/冻结用户,接口】;(用户状态变更后,需要刷新用户状态,即变更用户会话信息:我们一般通过“删除redis中会话信息,强制用户重新登录“来做的;)
What exactly happens after entering the URL in the browser?
Redis读写分离(三)
数据库调优:Mysql索引对group by 排序的影响
Flink Record has Long.MIN_VALUE timestamp (= no timestamp marker). Is the time characteristic
[Image Classification] 2021-CoAtNet NeurlPS
ES8 | async and await
22-08-06 Xi'an EasyExcel implements dictionary table import and export
中原银行实时风控体系建设实践
随机推荐
Excel中text函数5中常用方法
【无标题】
X射线聚焦系统
【office】word
Offensive and defensive world - ics-05
攻防世界——web2
正向传播和反向传播
各种attention的代码实现
移动端/嵌入式-CV模型-2019:MobelNets-v3
巧用Prometheus来扩展kubernetes调度器
Recommended download software
机器学习理论及案例分析(part3)--聚类
面试官:工作中用过锁么?说说乐观锁和悲观锁的优劣势和使用场景
67:第五章:开发admin管理服务:20:开发【解冻/冻结用户,接口】;(用户状态变更后,需要刷新用户状态,即变更用户会话信息:我们一般通过“删除redis中会话信息,强制用户重新登录“来做的;)
Is it safe to buy stocks with a straight flush?Will the funds be transferred?
Open source summer | Three ways to implement search in Flutter
Web优化躬行记(6)——优化闭环实践
LAN技术-5Eth-Trunk
Raspberry pie 】 【 without WIFI even under the condition of the computer screen
蔚来杯2022牛客暑期多校训练营6 ABGJM