IoC思想的原型推导 谁的控制权反转给了谁

本文介绍了IoC(控制反转)的基本概念,解释了如何通过IoC将对象创建的控制权从程序员转移给用户,从而降低代码耦合度。通过传统实现与IoC原型实现的对比,展示了如何在服务层动态注入DAO实现,使得用户可以根据需求选择不同的数据库读取方式。最后,总结了IoC的优势,包括提高灵活性和可维护性,并指出IoC的完整实现通常涉及依赖注入和配置文件(如XML)来进一步解除代码间的耦合。
摘要由CSDN通过智能技术生成

1、IoC的基础概念

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

——摘自百度百科

2、推导

显然上述的概念显得抽象,不得不点出一个问题:“控制反转”将谁的控制权反转,又给了谁?

直接了当的说,传统的程序主要的控制权在于程序本身,由程序员硬编码至程序中,换句话说,也可以说是由程序员控制。而客户的需求不断变化,每当新的需求提出,负责程序的工具人便需要修改源代码以适应用户的需求,这导致代码高度耦合。“我们为什么不把控制权交给用户呢?”,这个时候,控制反转(IoC)思想便应运而生。

将对象的创建这一权利从程序员手中转给用户,由用户决定生成的具体对象。

3、原型代码实现

这里举一个简单的例子:当不知道用户选择什么数据库来进行用户数据读取时(当然这只是个例子)


传统的实现

结构:

项目结构

DAO层:

public interface UserDao {
    String getUser();
}

public class UserDaoImpl implements UserDao{
    @Override
    public String getUser() {return "使用默认数据库获取用户";}
}

public class UserDaoMysqlImpl implements UserDao{
    @Override
    public String getUser() {return "使用Mysql数据库获取用户";}
}

public class UserDaoOracleImpl implements UserDao{
    @Override
    public String getUser() {return "使用Oracle数据库获取用户";}
}

Service层:

public interface UserService {
    void getUser();
}

public class UserServiceImpl implements UserService{
    //传统的使用接口,每次有新的需求就需要修改源代码
    //当用户想用默认的方式时
    private UserDao userDao=new UserDaoImpl();
    //当用户想用Mysql
    //private UserDao userDao=new UserDaoMysqlImpl();
    //当用户想用Oracle
    //private UserDao userDao=new UserDaoOracleImpl();
    //当用户想用......
    
    //由于采用的是硬编码(即写死代码),所以当用户需求不确定时,就需要不断地修改源码
    
    @Override
    public void getUser() {
        System.out.println(userDao.getUser());
    }
}

Test:

@Test
public void MyTest():{
    UserServiceImpl userService=new UserServiceImpl();
   	userService.getUser();
}

Console控制台显示:

"C:\Program Files\Java\jdk1.8.0_281\bin\java.exe" ...
使用默认数据库获取用户

Process finished with exit code 0

正如前文所说,这种传统工厂模式实现的弊端在于对象的创建完全硬编码在程序中,对象的创建将由程序控制,此时需求一旦发生改变就需要修改源代码。

传统工厂模式实现


IoC原型实现

项目结构不变

DAO层(不变):

public interface UserDao {
    String getUser();
}

public class UserDaoImpl implements UserDao{
    @Override
    public String getUser() {return "使用默认数据库获取用户";}
}

public class UserDaoMysqlImpl implements UserDao{
    @Override
    public String getUser() {return "使用Mysql数据库获取用户";}
}

public class UserDaoOracleImpl implements UserDao{
    @Override
    public String getUser() {return "使用Oracle数据库获取用户";}
}

Service层:

public interface UserService {
    void getUser();
}

public class UserServiceImpl implements UserService{
    
    private UserDao userDao;
	//由set方法实现动态值的注入
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    
    @Override
    public void getUser() {
        System.out.println(userDao.getUser());
    }
}

Test:

@Test
public void MyTest():{
    UserServiceImpl userService=new UserServiceImpl();
    UserDao userDao=null;
    //现在想要使用哪种方式将取决于用户的选择
    System.out.println("1.我想使用默认的方法进行获取用户数据");
    System.out.println("2.我想使用mysql进行获取用户数据");
    System.out.println("3.我想使用Oracle进行获取用户数据");
    Scanner sc=new Scanner(System.in);
    System.out.print("================\n输入你的选择:");
    int choice = sc.nextInt();
    switch (choice) {
        case 1:userDao = new UserDaoImpl();break;
        case 2:userDao = new UserDaoMysqlImpl();break;
        case 3:userDao = new UserDaoOracleImpl();break;
        default:break;
    }
    userService.setUserDao(userDao);
    userService.getUser();
}

Console控制台显示:

"C:\Program Files\Java\jdk1.8.0_281\bin\java.exe" ...
1.我想使用默认的方法进行获取用户数据
2.我想使用mysql进行获取用户数据
3.我想使用Oracle进行获取用户数据
================
输入你的选择:2
使用Mysql数据库获取用户

Process finished with exit code 0

此时可以发现,通过在DAO层中添加一个set方法可以实现动态的值的注入将对象的创建的控制权转换给用户,不再需要我们修改

IoC原型实现


4、总结

传统实现和IoC控制反转原型实现:
对比

细心的老哥可能会发现,以上提到的都还只是IoC的原型实现,这并不是IoC的“完全体”,这里主要是想向大家展示IoC的思想。以上的实现表面上是在一定程度上缓解了以上问题,但实质上这种代码耦合并没有改变。通过IoC模式可以彻底解决这种耦合,它把耦合从代码中移出去,放到统一的XML 文件中,通过一个容器在需要的时候把这个依赖关系形成,即把需要的接口实现注入到需要它的类中,这可能就是“依赖注入”说法的来源了。

再有,这种IoC模式有没有让你想起一个熟悉的Java特性——反射,利用Java 的“反射”编程,根据XML中给出的类定义生成相应的对象。从实现来看,以前在工厂模式里写死了的对象,IoC模式改为配置XML文件,这就把工厂和要生成的对象两者隔离,极大提高了灵活性和可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值