问题一:平时在设计类的时候往往会遇到以下情况,类a依赖于类b,同时类b又依赖于类a,这样就会造成循环依赖。
如果在类中存在循环依赖,就会导致,如果a中有改变可能会影响b,同时b如果有变化也会影响a(个人观点)。
在这个过程中,我又抽象出一个新的类c,这个类用来存放类a和类b相互依赖的部分,当a需要调用类b,在这个模型中可以直接去调用c。但是此时类c是不会去依赖类a和类b,我觉得这是一个难点,如果在不依赖类b和类a的前提下,完成以前一样的逻辑(这里我认为会存在很多重复的代码)。
q:在设计过程中,循环依赖是否是允许的?如何解决循环依赖?
问题二:
平时我们在用spring写业务逻辑的时候,当service a依赖service b和service c,service b依赖service c。每当这个时候我就会有强迫症,我想把service b 对service c的依赖干掉。在a中直接通过传参的方式把service c传给service b
如上所示,感觉在平时用spring框架的时候一些调用栈会很奇怪:
public class a{ private c c; private b b; public void methoda(){ c.methodc(); b.methodb(); } } public class b{ private c c; public void methodb(){ c.methodc(); dosomething(); } }
如上代码.每当这个时候我都想把在a中c.methodc()的结果返回值通过参数传给b.methodb(),但是这样会导致methodb()方法中多了一个参数。感觉在设计上又不是特别合理,因为我觉得在调用b.methodb()的时候是不需要感知c的存在的。
q:怎么用面向对象的角度去理解问题二这个场景。
谢谢
回复内容: 问题一:平时在设计类的时候往往会遇到以下情况,类a依赖于类b,同时类b又依赖于类a,这样就会造成循环依赖。
如果在类中存在循环依赖,就会导致,如果a中有改变可能会影响b,同时b如果有变化也会影响a(个人观点)。
在这个过程中,我又抽象出一个新的类c,这个类用来存放类a和类b相互依赖的部分,当a需要调用类b,在这个模型中可以直接去调用c。但是此时类c是不会去依赖类a和类b,我觉得这是一个难点,如果在不依赖类b和类a的前提下,完成以前一样的逻辑(这里我认为会存在很多重复的代码)。
q:在设计过程中,循环依赖是否是允许的?如何解决循环依赖?
问题二:
平时我们在用spring写业务逻辑的时候,当service a依赖service b和service c,service b依赖service c。每当这个时候我就会有强迫症,我想把service b 对service c的依赖干掉。在a中直接通过传参的方式把service c传给service b
如上所示,感觉在平时用spring框架的时候一些调用栈会很奇怪:
public class a{ private c c; private b b; public void methoda(){ c.methodc(); b.methodb(); } } public class b{ private c c; public void methodb(){ c.methodc(); dosomething(); } }
如上代码.每当这个时候我都想把在a中c.methodc()的结果返回值通过参数传给b.methodb(),但是这样会导致methodb()方法中多了一个参数。感觉在设计上又不是特别合理,因为我觉得在调用b.methodb()的时候是不需要感知c的存在的。
q:怎么用面向对象的角度去理解问题二这个场景。
谢谢
循环依赖当然是允许的,没有任何规定说依赖只能是单向的。看看设计模式中的中介者、观察者等模式,它们就是典型的循环依赖关系。以观察者模式为例:订阅者会依赖观察者,观察者需要通知订阅者所以也要依赖它们。
不能这样做。如果不是依赖关系设计有问题,那么a依赖b和c、b依赖c说明a和b确实需要c。如果像你说的那样把b对c的依赖干掉,那么b就没有存在的必要了,此时b将退化为a的“附属类”,或者说是a的“专用方法类”。也就是说,b的可复用性就会大打折扣,如果以后有其他类,比如d,也需要用到b的话,那么d将不得不也依赖c,这就把对b和c的依赖绑死了,但d未必需要c才能干活啊,仅仅是为了“满足”b就必须先弄一个c,是不是很奇怪?(如果d跟a一样确实也需要c那是可以的,这里说的是d本身不需要c的情况)
所以,首先确定b是否确实需要c,如果答案是肯定的,那就安心地这么干吧。
1、相互依赖确实是代码中让人纠结的坏味道,没有更好的设计方案的情况下,只能尽量不让这种混乱扩散到其他类。
2、对于分层设计,我个人是允许同一层的类之间相互依赖的,比如存在 service 层和 dao 层,前者依赖后者,而后者内部的类也可以相互依赖,但绝不允许 dao 层的类调用 service 层,一旦出现这种意愿,说明这部分逻辑本来就应该放在 service 层。