适配器模式,Adapter模式,也叫Wrapper模式(包装器)
Adapter这个词见的很多,比如springmvc里的SimpleControllerHandlerAdapter,slf4j里的AbstractLoggerAdapter
顾名思义:适配器是为目标寻找合适的类的方法或者对找到的方法进行改造(重写)从而完成方法的调用
适配器模式具体又分为两种:类适配器模式和对象适配器模式
本篇讲的是类适配器模式,对象适配器模式下次再说
类适配器模式对应继承关系
涉及到这几个角色:
Target:目标接口,需要一个method2方法的实现
Adaptee:被适配者(可以是类或者接口),仅有一个method1方法
Adapter:适配器,实现了Target接口,并继承了Adaptee方法
(图不重要看字)
具体的以slf4j中 LoggerFactory.getLogger(..)方法来说明
可以看到iLoggerFactory调用了其实现类Log4jLoggerFactory的getLogger方法,于是进入LoggerFactory
令人意外的是该类中并没有getLogger方法,别急,注意红色标注的地方,先进入AbstractLoggerAdapter,可以看到在此类中有一个getLogger方法,此外这个抽象类还实现了一个LoggerAdapter接口
LoggerAdapter接口的代码就不贴了,里面只有一个getLogger方法
所以iLoggerFactory.getLogger(name)调用的过程就很清楚了:调用的是Log4jLoggerFactory从AbstractLoggerAdapter继承的getLogger方法
结合我们开头的Target,此处指的就是iLoggerFactory,他需要一个getLogger方法,而LoggerAdapter(Adaptee)接口里有这个方法,但接口里的方法不能直接调用,
于是有一个抽象类AbstractLoggerAdapter实现了iLoggerFactory接口,并重写了其getLogger方法,但真正充当适配器角色的是AbstractLoggerAdapter的子类
Log4jLoggerFactory,iLoggerFactory通过它真正的调用了getLogger方法,
事实上,这之间还隐藏着一种被称为缺省适配的模式,即当一个接口(类)A想调用另一个接口B的某个方法时,直接写个类实现B接口的话,那么要实现B接口里的全部方法
这样我们虽然可以调用方法了,但却要实现相当多的冗余方法,通常的做法是使用一个抽象类C继承B接口,实现其方法(多数为空的方法体,有人称之为平庸的实现),再使用一个新的类继承C.
这样就可以直接调用(改造)我们需要的方法,你可能会说,这并没有简便,事实上编写抽象类继承接口的大多数工作java已经替我们完成了,我们需要做的只是继承该抽象类
到此类对象适配器模式就结束了,可以看到类适配器模式使用的是继承关系,这使得我们调用Adaptee的方法,只能静态的使用其一个子类
这是由继承决定的无法避免,如果我们希望动态的使用Adaptee的方法,即可以动态的选择其子类来调用我们的方法该怎么做呢?这就要用
到对象适配器模式了,下次再说