工厂方法通过定义中间层,只能将两个模块解耦,当一个业务需要至少三个相互依赖的模块互相调用才能运转时,就需要在这些模块之间定义中间人模块,这种设计就是中间人模式,也叫做中介者模式。
以进销存这样的常见业务为例:
这样的业务模式就形成了相互依赖,如图:
在实现业务代码时,几个类之间也是牵一发而动全身:
中间人模式则是引入一个中间人模块作为其余模块的交流中心,每个模块只负责自己的业务逻辑,模块之间不再相互交流,要交流就通过中间人进行,从而简化了各模块之间的耦合关系:
使用中间人模式解耦后的类图如下:
在接口层面存在两个层级:AbstractMediator 和 AbstractColleague:
修改后的场景类如下
显而易见,减少类间的依赖,把原有的一对多的依赖变成了一对一的依赖,同事类只依赖中介者,减少了依赖,当然同时也降低了类间的耦合。
中间人层会因业务模块的增加变得越加复杂
中间人模式简单,但是简单不代表容易使用,很容易被误用。在面向对象的编程中,对象和对象之间必然会有依赖关系,如果某个类和其他类没有任何相互依赖的关系,那这个类就是一个“孤岛”,在项目中就没有存在的必要了!类之间的依赖关系是必然存在的,一个类依赖多个类的情况也是存在的,存在即合理,那是否可以说只要有多个依赖关系就考虑使用中间人模式呢?答案是否定的。中间人模式未必能帮你把原本凌乱的逻辑整理得清清楚楚,而且中间人模式也是有缺点的,这个缺点在使用不当时会被放大,比如原本就简单的几个对象依赖关系,如果为了使用模式而加入了中间人,必然导致中间人的逻辑复杂化,因此中间人模式的使用需要“量力而行”!中间人模式适用于多个对象之间紧密耦合的情况,紧密耦合的标准是:在类图中出现了蜘蛛网状结构。在这种情况下一定要考虑使用中间人模式,这有利于把蜘蛛网梳理为星型结构,使原本复杂混乱的关系变得清晰简单。
最后,中间人模式很少使用接口或抽象类,这与依赖倒置原则是冲突的,也是由于中间人模式的特点而决定:
中介者模式是一个非常好的封装模式,也是一个很容易被滥用的模式,一个对象依赖几个对象是再正常不过的事情,且使用中介模式就必然会带来中介者的膨胀问题,但是要求使用中介者模式来封装这种依赖关系,这在一个项目中是很不恰当的。当业务模块之间产生 N-N 依赖关系,且不确定不确定或者有发生改变的可能,在这种情况下一般建议采用中介者模式,降低变更引起的风险扩散,典型的就是产品开发,往往在迭代的过程中存在诸多不确定性,使用中间人模式能够将细分的模块组合成灵活的功能。与之相对的是项目开发,已项目验收为目标,设计相对固定,在明确了模块之间有 N-N 依赖,则使用中间人模式。