当前位置: 首页 > news >正文

IOC控制反转的解耦(相比于直接new对象的正向控制)

直接new对象,是你在主动寻找和创建你需要的“零件”;而 IoC 则是你告诉一个“管家”你需要什么“零件”,由“管家”帮你找到或创建好,然后递给你。

这个“管家”就是 IoC 容器(比如 Spring 容器),而“递给你”的这个动作,最常见的实现方式就是依赖注入(Dependency Injection, DI)

下面我们通过一个例子来解释清楚。

场景:UserService 需要使用 UserDao 来操作数据库

假设我们有一个 UserService 类,它负责用户相关的业务逻辑,比如用户注册。它需要依赖一个 UserDao 类来与数据库进行交互。UserDao 是一个接口,它有一个具体的实现类 UserDaoImpl

Java

// 数据访问层接口
public interface UserDao {void addUser(User user);
}// 接口的实现类
public class UserDaoImpl implements UserDao {@Overridepublic void addUser(User user) {System.out.println("数据库:添加用户 " + user.getName());}
}

1. 直接 new 一个对象(正向控制)

在这种方式下,UserService 类需要自己负责创建它所依赖的 UserDaoImpl 对象。

代码示例:

Java

public class UserService {// UserService 内部自己创建了 UserDaoImpl 实例private UserDao userDao = new UserDaoImpl();public void register(User user) {// ... 其他业务逻辑,如检查用户名密码等userDao.addUser(user);}
}

分析这种方式的问题(为什么会耦合):

  1. 高度耦合UserService 和具体的实现类 UserDaoImpl 紧紧地“绑死”在了一起。UserService 的代码里写死了 new UserDaoImpl()
  2. 难以更换实现:如果有一天,我们不想用 UserDaoImpl 了,想换成一个新的、性能更好的 UserDaoMongoImpl (用 MongoDB 数据库),我们必须修改 UserService 的源代码,把 new UserDaoImpl() 改成 new UserDaoMongoImpl()。如果有一百个类都依赖 UserDaoImpl,你就得改一百次。
  3. 难以测试:当我们要对 UserService 进行单元测试时,我们希望用一个“假的” UserDao (Mock 对象)来模拟数据库操作,而不是真的去连接数据库。但由于 UserDaoImpl 是在 UserService 内部 new 出来的,我们根本没有办法在外部替换它,导致单元测试非常困难。

总结:控制权在 UserService 手中,它主动去创建依赖,导致了它和依赖的实现类之间强烈的耦合关系。

2. 使用 IoC / DI (控制反转)

在 IoC 模式下,UserService 不再自己创建依赖,它只负责“声明”自己需要一个 UserDao 类型的依赖。对象的创建和管理权被交给了 IoC 容器(例如 Spring)。

代码示例:

Java

// 使用 Spring 框架的注解来示意
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service // 告诉 Spring:这个类交给你管理
public class UserService {// 依赖一个接口,而不是具体的实现类private final UserDao userDao;// 通过构造函数注入依赖@Autowiredpublic UserService(UserDao userDao) {this.userDao = userDao;}public void register(User user) {// ... 其他业务逻辑userDao.addUser(user);}
}// UserDaoImpl 也需要被 Spring 管理
@Repository // 告诉 Spring:这个数据访问层类也交给你管理
public class UserDaoImpl implements UserDao {@Overridepublic void addUser(User user) {System.out.println("数据库:添加用户 " + user.getName());}
}

分析这种方式的好处(为什么会解耦):

  1. 实现了解耦UserService 只依赖于抽象的 UserDao 接口,它根本不知道、也不关心最终传进来的是 UserDaoImpl 还是 UserDaoMongoImpl。它只知道“我需要一个能操作用户的 DAO,是谁不重要,能用就行”。

  2. 轻松更换实现:如果我们想把 UserDaoImpl 换成 UserDaoMongoImpl,我们完全不需要修改 UserService 的代码。只需要在 Spring 的配置中告诉它:“以后凡是需要 UserDao 的地方,都给他 UserDaoMongoImpl 的实例”。

  3. 非常容易测试:在进行单元测试时,我们可以非常轻松地手动创建一个 MockUserDao 对象,然后通过 UserService 的构造函数传进去,从而实现对 UserService 的隔离测试。

    Java

    // 测试代码
    @Test
    void testRegister() {// 创建一个假的 DaoUserDao mockDao = new MockUserDao(); // 手动注入这个假的 Dao 来创建 UserServiceUserService userService = new UserService(mockDao);userService.register(new User("test"));// ... 断言 mockDao 的方法是否被正确调用
    }
    

总结UserService 失去了创建依赖的控制权,这个控制权被“反转”给了 IoC 容器。容器负责创建好 UserDaoImpl 的实例,然后通过依赖注入(这里是构造函数注入)的方式“塞”给 UserServiceUserService 从一个主动的创建者,变成了一个被动的接收者。

http://www.sczhlp.com/news/116234/

相关文章:

  • 墨者学院 浏览器信息伪造
  • AT_arc156_c [ARC156C] Tree and LCS
  • 完整教程:ARM指令集总结
  • 什么行业必须做网站杭州网站建设服务
  • 做直播网站软件有哪些软件公司网站制作排名
  • 北京网站制作设计推广公司嘉兴网站制作报价
  • 网站后台帐号ns解析网站
  • 封神台 第三章:为了更多的权限!留言板!
  • 第一篇
  • 网站建设实训心得体会网站建设与网页设计是什么
  • 昆山花桥做网站免费网页制作工具下载
  • 安徽省铜陵市建设局网站微网站如何建立的
  • 怎么让别人看到自己做的网站高清图片素材网站免费下载
  • 网站注册价格上海最专业的seo公司
  • 个人 中小企业公司网站建设方案正规网站开发流程
  • 学校做网站有些什么好处怎么用dw制作网站
  • C#开发ONVIF客户端与RTSP播放库指南
  • 一行命令查看docker所有网络 + 子网
  • ECT-OS-JiuHuaShan框架元推理,是马克思主义与我思故我在的完美统一,是超越自我
  • 网站建设经费计划内容网站版本功能列表
  • 建设网站跟服务器得关系网络公司品牌推广
  • 百度找不到我的网站了重庆软件外包公司
  • 做网站要上海建站外贸
  • 网站带支付源码wordpress创建自己的地图
  • 丹阳网站建设策划wordpress更改轮播图
  • asp.net 网站安装包移动网站开发教程下载
  • 在哪个网站可以查做项目中标的免费建立教育网站
  • Salesforce 管理员:是终点,还是跳板?
  • 记一次内务培训
  • CH584 CH585 复位状态寄存器