为啥依赖注入能比直接new 对象降低耦合度,我总是不理解

zyq654321 2021-05-23 07:17:25
比如A对象里面要调用B对象,B要调用C对象....

ClassA {
public void mathod1() {

Class B b1=new ClassB();
b1.mathodb1();
}
}

ClassB {
public void mathodb1() {

Class C C1=new ClassC();
C1.mathodc1();
}
}

ClassC {
public void mathodc1() {
.....
}
}
我想用ClassA的 mathod1 ,直接(new ClassA()).mathod1()有啥不好呢,非要注入一个ClassA,不嫌麻烦吗
...全文
33331 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
沧半闲 2023-03-15
  • 打赏
  • 举报
回复

作为一个boss,我现在有一份工作,需要两个部门合力完成,我会建立一个或多个新岗位或职责到两个部门中,我不考虑具体谁去负责,部门的负责人去安排具体的人,干得不好我就问责部门负责人,我需要知道具体谁干得吗,不需要,低耦合对应到管理上就是要明确职责,方便问责也方便换人。

他们都知道 2022-01-14
  • 打赏
  • 举报
回复 1

创建对象 和 使用对象 分离。
你这里写的是最简单的new的方式,如果是复杂依赖、多入参。那可维护性就要降低很多了。

幕后眼光 2021-12-10
  • 打赏
  • 举报
回复

细想一下,未来你新增一个 class D,你要改 class A 内部代码,这就违反“开闭原则”了,通过传参(注入)的形式,可以达到解耦,方便后续扩展。

灵魂孤独者 2021-11-13
  • 打赏
  • 举报
回复 6

最直观的好处有两点:
1.默认使用单例模式能大大减少JVM堆内存使用;
2.【依赖注入 最主要的作用是 控制反转】稍微修改下楼主的例子:
场景:除了B依赖A之外还有,C,D,E,F,G等等都依赖A。
如果都直接使用new A()的方式来使用A。那么当业务发生改变发现A不在再满足需求需要调整业务逻辑有了新的实现类A1,那就得重新修改所有使用A的B,C,D,E,F,G等等使用类的代码才能实现。而如果使用依赖注入的方式,就只需要在配置的一个地方修改即可。

qq_39936465 2021-05-27
  • 打赏
  • 举报
回复 1
引用 楼主 zyq654321 的回复:
比如A对象里面要调用B对象,B要调用C对象.... 我想用ClassA的 mathod1 ,直接(new ClassA()).mathod1()有啥不好呢,非要注入一个ClassA,不嫌麻烦吗
耦合性的概念就是代码对参数的依赖紧密度,依赖注入其实是一种代码和参数分离,你可以把配置文件看作一个参数列表,所有代码都是去参数列表找参数,这样当需要修改参数时我们不需要关心代码,只需要修改参数列表,这样自然降低了耦合度。
千梦一生 2021-05-27
  • 打赏
  • 举报
回复
引用 8 楼 zyq654321 的回复:
【依赖注入 最主要的作用是 控制反转】 ,反转的目的不是为了降低耦合吗,否则反转干啥呢,还要配置一大堆东西,不是更加麻烦吗,
误区:降低耦合和减少代码量是无关的。甚至说来很多时候解耦恰恰增加代码量。会“麻烦”起来 几年前学过依赖注入的概念,不知道我记得是否准确。 其实就是一个接口问题。 工厂给的是一个类似于车辆底盘的东西。 你可以想一个问题【可否每个模块设计时,接口不去考虑和其他模块匹配的问题。当然如果真这样,那必然会出现两个模块无法联通工作。如何是好?这时候需要设计一个中间件。此时,这些接口匹配问题均由中间件解决。每个模块仍然各独立。只需要考虑的是各个模块如何接入中间件这个问题】【这就很像现实中的转接线如果设计一个车辆底盘,标准化了允许接入的轮胎大小,螺丝规格之后。那么轮胎、方向盘按要求整就放的进去。它们根本不关心这个主题是一直鸡,还是一盘麻婆豆腐。修改需求轮胎需要改成正方形,只需要改轮胎,其它任何地方都不需要变动
青阳令 2021-06-21
  • 举报
回复
@千梦一生 你说的好像是接口的概念啊。
xiaoxiangqing 2021-05-27
  • 打赏
  • 举报
回复
注入就相当于一个静态对象,所有的都是用的同一个
groovy2007 2021-05-27
  • 打赏
  • 举报
回复 8
这个要从依赖注入的历史说起。这里有个例子 https://www.w3cschool.cn/wkspring/t7n41mm7.html
假设我们开发一款文本编辑器,其中用到了一个SpellChecker。另外假设有多个不同的SpellChecker实现。我们不希望在代码里写死用哪个SpellChecker,这样不够灵活。代码如下:

public class TextEditor {
private SpellChecker spellChecker;
public TextEditor(SpellChecker spellChecker) {
System.out.println("Inside TextEditor constructor." );
this.spellChecker = spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}

如何在创建程序的时候指定用哪个SpellChecker呢?Spring早期的做法是通过xml配置文件:

<bean id="textEditor" class="com.tutorialspoint.TextEditor">
<constructor-arg ref="spellChecker"/>
</bean>

<bean id="spellChecker" class="com.tutorialspoint.SpellChecker">
</bean>

这样的话,spring就帮你创建了一个textEditor,并且帮你“注入”了一个spellChecker。如果想更换spellChecker只需要改变配置文件就行了,不需要重新编译代码。

可是现在大家都不这么写了,基本上都是用注解。

public class TextEditor {
private SpellChecker spellChecker;

// 自动寻找SpellChecker的默认实现,如果只有一个实现的话。或者通过其他注解显式指定用哪个实现。
@autowired
public TextEditor(SpellChecker spellChecker) {
System.out.println("Inside TextEditor constructor." );
this.spellChecker = spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}

这样其实和硬编码差不多(可能少敲几个字符吧,new MySpellChecker()),有任何改动还是需要重新编译。TextEditor又和具体的SpellChecker耦合在了一起。

为什么会发生这种转变?可能大家发现绝大多数的接口其实只有一个实现,而且也不太可能在别的项目里重用,所以耦合就耦合了吧。
青阳令 2021-06-21
  • 举报
回复 1
@groovy2007 解释的很好,受教啦
qq_50558878 2022-03-01
  • 举报
回复
@groovy2007 谢谢学到了
qybao 2021-05-26
  • 打赏
  • 举报
回复 1
你是真不明白我所说的内容,还是故意钻牛角尖? 这里所谓的不改变代码是指整个处理流程(或框架)的代码不改变。你增加新的业务,当然要加新的业务实现类代码(代码不会凭空生成),但这新增的业务实现代码不影响你的主处理,也就是相当于例子中的class Main(不变指的是这里)。如果不用注入,你的class Main每次都要修改。当然,你也可以用些设计模式来达到Main不变,但毕竟这些设计模式的代码是由你自己来维护,你能保证这些代码有多大的扩展性(能确保今后都不用修改)?即然有成熟的框架,为何不直接使用?尤其是在追求开发效率的当下。
zyq654321 2021-05-26
  • 打赏
  • 举报
回复
谢谢大家的热情讨论,通过讨论和网上查找资料,我基本理解了注入依赖,依赖注入主要目的是为了降低耦合,单例模式能大大减少JVM新生代eden区内存 ,对使用频率超高的类有用 ,但是会长期占用JVM静态区和堆区的老年代,使用频率不高的东西使用单例模式弊大于利,所以一定要理解各种模式才能真正地用好。
冰思雨 2021-05-26
  • 打赏
  • 举报
回复
我和楼主有不同的理解。 依赖注入的主要目的,应该和降低耦合没有什么关系,依赖注入的主要目的应该是代码的复用。 通过配置各个类之间的依赖关系,可以灵活的复用这些类的代码(功能)或者资源(不仅仅是内存数据资源,还包括文件,网络等等,看项目需要)。 楼主说的降低耦合性,这个不是没有只是,不是主要目的。 A 和 B 有依赖关系,如果不适用DI,自己创建的话,是明显的紧密耦合;如果使用DI(依赖注入)的话,A 和 IoC 容器耦合了,B 也和 IoC 容器耦合了,A 和 B 的耦合关系,被 IoC 容器转嫁了。其实就是,原本两个类的夫妻关系,现在变成特殊的三角关系了。我并不觉得这对软件设计有什么出彩的好处。 当然,在使用 IoC 容器的时候,面向接口编程,可以更好的进行降低耦合或者解除耦合,但是,这个与楼主说的应该不是一个主题。 另外, [怎么在不改变代码的前提下,生成不同的实现类a] 这个是要体现多态还是有什么具体的业务场景要求这样呢? 如果是要处理业务逻辑的话,可以参考策略模式,这个很好实现的。 [怎么在不改变代码的前提下,扩展a的属性] 这个可以参考装饰器模式来实现。 当然,以我的理解,这些好像都和楼主说的内容,不是同一个主题吧。 依赖注入就是一种设计思想,把类(对象)直接的关系通过配置文件的形式体现出来,然后,由容器进行注入。仅此而已。 你要非说它能降耦吧,也是可以的,反正这么一折腾,所有依赖注入的对象,都和容器有耦合关系。彼此的耦合关系被转嫁到容器上面了一些。
maradona1984 2021-05-25
  • 打赏
  • 举报
回复
"依赖注入能比直接new 对象降低耦合度"这个前提是依赖接口,如果你是直接依赖实现类(当然也可以注入子类),注入的意义大概也就统一的规范和aop了
=PNZ=BeijingL 2021-05-24
  • 打赏
  • 举报
回复 1
我想用ClassA的 mathod1 ,直接(new ClassA()).mathod1()有啥不好呢,非要注入一个ClassA,不嫌麻烦吗

注入的方式能实现你处理的ABC三个对象都是唯一的,对象里持有的属性访问都是对象的实时的数据
如果用new的方式,比如(new ClassA())是新创建1个对象,这样A对象里的属性都是新初始化的,
你考虑下这个场景: 如果在同一个程序中, 每次都new 对象, 那么对象中持有的属性的数据都会丢失,数据很难传递,
zyq654321 2021-05-24
  • 打赏
  • 举报
回复
[所以,你思考一下,怎么在不改变代码的前提下,生成不同的实现类a,怎么在不改变代码的前提下,扩展a的属性。想明白这两个问题,你就明白注入的意义了。] 你搞错了把,不写代码哪里来的不同的实现类
编号灬9527 2021-05-24
  • 打赏
  • 举报
回复
[所以,你思考一下,怎么在不改变代码的前提下,生成不同的实现类a,怎么在不改变代码的前提下,扩展a的属性。想明白这两个问题,你就明白注入的意义了。]很精辟,多读读几次多理解一下,
qybao 2021-05-24
  • 打赏
  • 举报
回复 2
这个问题,有那么难理解吗? 来看这么一个例子 interface IA {} //业务处理接口 class A1 implements IA {} //业务实现类 class Main { // 注入IA实例 IA a; private dosomething() { a.xxx(); //直接使用a } } 好了,再来讨论换个业务实现类 class A2 implements IA {} 此时,用注入的方式,只要修改配置文件即可,代码不用改 如果不用注入的方式,那么在dosomething里a就要自己去new,这种动态的new,你不知道业务到底是什么实现类,没法控制。就算你用反射,也是有局限,因为没法动态a的属性(假设业务实现类a的属性有所变化),而配置文件,只需要再配置a的property即可,代码还是不用变。 所以,你思考一下,怎么在不改变代码的前提下,生成不同的实现类a,怎么在不改变代码的前提下,扩展a的属性。想明白这两个问题,你就明白注入的意义了。
zyq654321 2021-05-24
  • 打赏
  • 举报
回复
【如果采用楼主的那种编程方式,每调用一次函数,都现场 new 一个对象,然后调用对象的方法,这样的话,如果频繁调用函数,意味着函数内部会频繁的创建对象,内存使用会出现突发性暴增的情况,当然,也会触发GC。如果使用依赖注入的话,函数内的对象,可能会声明为类的成员变量,而且由于是单例的,每次函数调用,都没有必要再次创建。】这个我说了,是单例模式的优点,不是依赖注入的优点,依赖注入也可以采用多例模式
zyq654321 2021-05-24
  • 打赏
  • 举报
回复
【依赖注入 最主要的作用是 控制反转】 ,反转的目的不是为了降低耦合吗,否则反转干啥呢,还要配置一大堆东西,不是更加麻烦吗,
zyq654321 2021-05-24
  • 打赏
  • 举报
回复
[所以,你思考一下,怎么在不改变代码的前提下,生成不同的实现类a,怎么在不改变代码的前提下,扩展a的属性。想明白这两个问题,你就明白注入的意义了。] 不改变代码的前提 ,如何生成不同的实现类a ,你不是要做另外一个类去实现interface么,这个不用码代码啊,码一个新的类不麻烦,new A改成new B就麻烦了么,还是不理解。
冰思雨 2021-05-24
  • 打赏
  • 举报
回复
依赖注入 最主要的作用是 控制反转 , 可以理解为一个大型的对象工厂,里面的对象统一由这个对象工厂来管理。 至于楼主说的降低耦合,应该是通过面向接口编程来实现的,至少我是这么理解的。 楼主举的这个例子,即没有体现控制反转,也没有体现面向接口的编程思想,所以,无法看出可以降低耦合这个特性。 想要降低耦合,主要还是看软件设计,你的代码设计的好,不使用依赖注入,依然可以低耦合。 所以,降低耦合,其实和 依赖注入,并没有什么必然的关系。 依赖注入,对楼主的样例代码而言,一般情况下,依赖注入的对象,都是默认单例的,这对内存的管理有好处。 如果采用楼主的那种编程方式,每调用一次函数,都现场 new 一个对象,然后调用对象的方法,这样的话,如果频繁调用函数,意味着函数内部会频繁的创建对象,内存使用会出现突发性暴增的情况,当然,也会触发GC。如果使用依赖注入的话,函数内的对象,可能会声明为类的成员变量,而且由于是单例的,每次函数调用,都没有必要再次创建。 另外,降低耦合,必然要向 加强封装特性 和 接口隔离 这两个方向努力。封装方面,设计类的时候成员变量和函数要抽象的得体一些;接口隔离方面,隔离要尽量彻底,尽量避免依赖关系才行。
加载更多回复(3)
项目工程资源经过测试运行,功能上ok,可复现复刻,拿到资料包后可实现复刻出一样的项目,本人系统开发经验充足(全栈),有任何使用问题欢迎随时与我联系,我会努力及时为您解惑,提供帮助 【资源内容】:包含源码、工程文件等。资源质量优质,放心下载使用!可参考实现复现;设计报告也可借鉴此项目工程;该资源内项目代码都经过测试运行,功能ok 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 【提供帮助】:有任何使用上的问题欢迎随时与我联系,及时抽时间努力解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 质量优质,放心下载使用。下载后请首先打开说明文件(如有);项目工程可实现复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途,网络商品/电子资源资料具可复制性不支持退款。质量优质,放心下载使用。
资源下载链接为: https://pan.quark.cn/s/1f197bf22c2c 随着疫情防控形势的复杂多变,防疫物资的高效管理成为保障社会正常运转的关键环节。传统管理方式存在效率低、信息不透明等问题,难以满足现代疫情防控的动态需求。因此,开发一套基于现代化信息技术的防疫物资管理系统具有重要的现实意义。 本研究旨在通过构建一套高效的防疫物资管理系统,实现物资信息的实时更新与精准管理,提高物资调配效率,降低管理成本,为疫情防控工作提供有力支持,同时为相关领域的信息化建设提供参考借鉴。 本研究将围绕防疫物资管理系统的设计与实现展开,包括系统需求分析、系统设计、系统实现以及系统测试等环节,重点解决系统功能模块的开发与优化问题。 Eclipse是一款功能强大的集成开发环境,支持多种编程语言,为本系统开发提供了便捷的代码编写与调试工具。 JSP(Java Server Pages)是一种基于Java的动态网页技术,能够实现页面内容的动态生成,为系统的用户界面展示提供了技术支持。 B/S(浏览器/服务器)结构是一种网络应用架构,用户通过浏览器访问服务器上的应用程序,具有易于部署、维护方便等优点,适用于本系统的网络环境。 MySQL是一种开源关系型数据库管理系统,具有高性能、高可靠性和易用性等特点,为系统的数据存储与管理提供了可靠的解决方案。 Tomcat是一个开源的Java Servlet容器,支持JSP和Servlet技术,能够高效地运行Java Web应用程序,是本系统运行的重要支撑平台。 当前信息技术的快速发展为本系统的开发提供了成熟的技术基础,相关技术的稳定性和兼容性能够满足系统开发的需求。 系统开发所需的技术资源和硬件设备成本相对较低,且能够有效降低防疫物资管理的运营成本,具有良好的经济可行性。 系统能够提高防疫物资管理的效率和透明度,符合社会对疫情防控工作的需求,具

67,549

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧