解耦都是需要代理的。本质上并不存在没有代理就发生两个部件之间解耦的情况。
耦合,指的是两个协作的部件的关系。
A和B发生了协作,则A和B的关系是耦合。
如果A和O,P,Q,S…(简称集合F)协作,则A就和集合F发生了耦合,如果A发生了变化,想要维持系统正常,那么集合F就需要顺应A的变化而变化,以保持协作有效。同样的,集合F中的任何一个发生了变化,A也需要发生变化(至少是局部的变化),以保持协作有效。
所以,就算A具有多种工作方式,来分别同集合F协作,它依然是同集合F耦合的。
要想让A与集合F解耦,只有通过增加一个代理(B)来实现。
代理B有两种方式完成自己的工作:
-
提供一套它制定的协议给A和集合F,让A和F都按B的安排来工作。(例如"USB数据线",它告诉手机怎么传输数据,同时告诉电脑怎么接收数据,手机和电脑按照"USB数据线"的安排来工作;例如RabbitMQ)
这种工作方式,本质上是将A与F的耦合,拆成了 A与协议B的耦合 + F与协议B的耦合。也就是将"部件和部件"的耦合拆为了"部件和协议"的耦合
-
它作为话事人,分别适配集合F的每一个元素。(例如翻译软件,可以将所有语言翻译为中文;例如JVM)
这种工作方式,本质上是将A与F的耦合,拆成了 A与B的耦合 + F与B的耦合。本质上还是"部件和部件"的耦合,只是多了B作为A和F变化的缓冲区。
显然工作方式1是更为优秀的,但工作方式2有其存在的原因。当两个已经独立存在的系统想要发生协作时,几乎只有工作方式2能站出来解决问题。比如两个语言不通的人交流;比如windows跑java,macOS跑java。当我们架构系统的时候,应该尽可能发现那些可以被工作方式1解耦的点,一旦系统开始施工,要用工作方式1解耦就会带来额外的时间和精力开销。
总结一句:架构的目标是,让一切通过协议耦合!