首页 > 代码库 > 适配器模式

适配器模式

1.适用于代码接口的转换,使得按不同标准设计出来的模块能彼此调用。此处接口指的不仅是狭义的类与对象的接口,也包括引用的dll之间,html与js之间,一切彼此引用的模块之间,调用方通过适配器使用被调用方。

 

2.适配器的作用在于为被调用的模块提供标准化的接口,既做到了适应变化,有能方便管理和排除bug,还能其加强功能。

比如,A调用B,现在要调用C,C与B接口不同,那么构造模块D与B接口相同;A调用D,而D处理以后请求转发C,则原先场景(A)里的代码皆不用改。实现了场景的复用。

 

各种模式口水书好用对象-接口适配来阐述原理,有时候补充强调,说本模式依赖面向接口和里氏替换原则,又说主要适用修改环境。这些说法听起来像是某本国外设计模式原理书的读后感,或者是对别人举出范例生存活剥,而不是真正理解。

 

首先,适配器模式的精髓在于应用,而口水书的恰恰脱离了应用场景A而大谈B与D的关系,因为应用场景A大量,复杂的使用了B,所以才会产生出D来欺骗A,让A以为在调用B,这个设计模式才有最基本的价值,即减少修改,用扩展代替修改。如果A不复杂的话,本身修改就少,使用适配器就是多次一举,画蛇添足。书中往往对A的复杂程度一笔带过,这说明执笔人实际上在空谈意境,无病呻吟。

 

其次,用类和对象来阐述只适合于拆解结构,纯粹教学,口水书号称实际应用中这样做,实际应用中多半不必这么做,或者说,可以这么做,但是不叫适配器模式。实际应用中,A,B,C不存在修改的可能性,A是庞大复杂,B,C作为功能类不可能复杂,只能说是没有源码,实际上对C的适配,我完全可以说是构造,可以把C看做是采上来的数据。

设计模式的特点,必然是别人想不到,以为要重写的东西,如果是闭着眼睛就能想到的东西,没有模式这一说。面向接口实际上已经考虑了适配问题,整个A模块就是一个适配口,这时候不存在什么修补问题,只有A不用接口调用B的时候,才存在适配,这时我构造一个新模块,占用B的名字和命名空间,然后我在设法引用C或者B,这实际上没多少工作量,实际上这才是真正的修补。

 

适配的应用场合,依赖于两个较胖的模块,一个较瘦的接口,或者说较低的耦合,如果是模块较胖,接口也很胖,然后我要把这个接口完全“适配”起来,其付出的工作成本就比较高。比较明智的做法,是在场景模块调用功能模块时,专门做一个调用模块D(比如说,某Helper类),就是说,我这个模块相当于接口,然后我限制这个模块方法的数量。D又可以相当于控制中枢,在调用D的两端,A和B会各自进化,D倾向于协助B自动实现功能,而不是依赖于来自A的请求,如果有一天,要把B换成C,我只要在D里加一个分支选择即可,A根本不知道调用的是谁。这样做,即使不能把握代码的进化的控制方向(比如功能模块使用开源代码),也能够实现适配的效果;这样做,A的代码可以真正一点都不用改。

口水书里介绍的,只是在接口编程中临时制作一个适配头的方法,接口本身就尼玛是适配器,适配在这里基本上聊胜于无,且实际操作中,A,B距离太近,很容易产生一些耦合接口,即只有B才能提供的接口;本人描述的适配器,强制场景模块调用功能模块时使用适配单元,适配单元与功能单元实现了某种框架级别的分工,适配单元代替接口隐藏了功能单元的方法,适配单元本身有功能代码甚至代码集,增加了调用时腾挪周转的空间,大大降低了专有接口出现的可能性,降低了功能单元与场景单元的耦合。

适配的出现,可以是对接口不同的一种修补,也可以就是了方便代码自由进化而进行的有意设计。写场景代码时要注意这一点,对于功能专业性比较强的模块进行大量引用,或者通俗说,胖场景类引用胖功能类,要用适配器进行衔接并限制接口。一般来说,所有开源代码都要用适配器,要建立某种“注册-使用”机制。业务逻辑层可以看做就是表现层与数据持久层之间的适配器。使用适配器以后的程序,好像设了水密舱的渡船,容易发现漏水点。比如功能模块出问题,那么所有同接口调用处都会出问题,如果只有某个调用处出问题,那么是场景模块出了问题,因为我调用的代码常年不改的,而且是规范统一的,所以一定是其他代码出了问题。这样在代码级别实现了引用虽多,耦合极低。

 

总的来说,适配器类应是一种对胖场景类提供通向胖功能类的瘦接口的自动化类,它有两个思想,其一,瘦接口,低耦合;其二,自动化,带功能的接口,实体接口。

 

适配器模式