適配器模式(Adapter Pattern):將一個接口轉(zhuǎn)換成客戶希望的另一個接口,使接口不兼容的那些類可以一起工作,其別名為包裝器(Wrapper)始腾。適配器模式既可以作為類結(jié)構(gòu)型模式,也可以作為對象結(jié)構(gòu)型模式空执。
- 我的技術(shù)博客:https://nezha.github.io浪箭,https://nezhaxiaozi.coding.me
- 我的簡書地址:http://www.reibang.com/u/a5153fbb0434
- 本文的demo地址:DesignPatterns/AdapterPattern
適配器模式主要有兩種模式:1.類適配器模式
;2.對象適配器模式
其中:
類適配器模式
主要使用的是繼承
的思想辨绊;對象適配器模式
使用的組合引用
的思想奶栖。
不管哪種模式下,適配者模式的主要組成部分有三部分:
目標(biāo)(Target)角色
:這就是所期待得到的接口门坷。注意宣鄙,由于這里討論的是類適配器模式,因此目標(biāo)不可以是類默蚌。源(Adaptee)角色
:有目標(biāo)(Target)角色
的部分功能冻晤,但是還是不滿足或者是源(Adaptee)直接不滿足目標(biāo)的接口功能,需要配置它敏簿。適配器(Adapter)角色
:適配器類是本模式的核心明也。適配器把源接口轉(zhuǎn)換成目標(biāo)接口宣虾。顯然,這一叫色不可以是接口温数,而必須是具體類绣硝。
UML圖解讀
下圖是類適配器的UML圖,其中Target
是目標(biāo)接口撑刺,含有兩個待實現(xiàn)的方法鹉胖;Adaptee
是源接口(需要被改造或者擴展),它有一個實現(xiàn)方法operateA
够傍;然后適配器Adapter
類implements
了Target
接口甫菠,并且集成了Adaptee
源接口。所以通過適配器類就可以有完整的Target
接口功能了冕屯。最后在客戶端使用中就可以將Target
接口的實例化指向Adapter
類了寂诱。
還有一種比較常見的適配器就是對象適配器了。Target
接口和Adaptee
源接口都沒有變化安聘;最大的變化還是適配器類了痰洒,首先Adapter
類放棄使用繼承而是使用引用的方式來引入源接口,然后Adaptee
的實例對象也是通過構(gòu)造方法延遲注入了浴韭;最后還是需要實現(xiàn)Target
接口的兩個方法丘喻,只不過operateA
是通過Adaptee
源的實例對象執(zhí)行的。
類適配器
/**
* @Description: 目標(biāo)接口 <br>
*/
public interface Target {
//1.operateA是在源(Adaptee)中有實現(xiàn)的
void operateA();
//2.operateB在源(Adaptee)中沒有實現(xiàn)念颈,需要使用適配器
void operateB();
}
/**
* @Description: 源(Adaptee)角色 <br>
*/
public class Adaptee {
public void operateA(){
System.out.println("我是已經(jīng)實現(xiàn)的operateA");
}
}
/**
* @Description: 適配器(Adapter)角色 <br>
*/
public class Adapter extends Adaptee implements Target {
//其中operateA通過繼承的方式已經(jīng)集成到Adapter中了
@Override
public void operateB() {
System.out.println("我是通過適配器實現(xiàn)的operateB");
}
}
/**
* @Description: 類適配器模式 <br>
*/
public class AdapterClient {
public static void main(String[] args) {
//目標(biāo)Target是通過適配器Adapter獲得的
Target adapter = new Adapter();
adapter.operateA();
adapter.operateB();
}
}
結(jié)果:
我是已經(jīng)實現(xiàn)的operateA
我是通過適配器實現(xiàn)的operateB
對象適配器
public interface Target {
//1.operateA是在源(Adaptee)中有實現(xiàn)的
void operateA();
//2.operateB在源(Adaptee)中沒有實現(xiàn)泉粉,需要使用適配器
void operateB();
}
public class Adaptee {
public void operateA(){
System.out.println("在源(Adaptee)中實現(xiàn)的operateA");
}
}
public class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee){
this.adaptee = adaptee;
}
@Override
public void operateA() {
//通過傳入的源對象實現(xiàn)operateA
this.adaptee.operateA();
}
@Override
public void operateB() {
System.out.println("我是通過適配器的實現(xiàn)接口實現(xiàn)的operateB");
}
}
public class AdapterClient {
public static void main(String[] args) {
//1.實例化源 Adaptee
Adaptee adaptee = new Adaptee();
//2.創(chuàng)建適配者對象,并且傳入源
Target target = new Adapter(adaptee);
target.operateA();
target.operateB();
}
}
結(jié)果:
在源(Adaptee)中實現(xiàn)的operateA
我是通過適配器的實現(xiàn)接口實現(xiàn)的operateB
應(yīng)用場景
Spring
中也有適配器模式的典型應(yīng)用榴芳。
在 Spring
的 AOP
中嗡靡,使用的 Advice
(通知)來增強被代理類的功能。Spring
實現(xiàn)這一 AOP
功能的原理就使用代理模式(1翠语、JDK動態(tài)代理叽躯。2、CGLib字節(jié)碼生成技術(shù)代理肌括。
)對類進行方法級別的切面增強点骑,即,生成被代理類的代理類谍夭, 并在代理類的方法前黑滴,設(shè)置攔截器,通過執(zhí)行攔截器的內(nèi)容增強了代理方法的功能紧索,實現(xiàn)的面向切面編程袁辈。
Advice
(通知)的類型有:MethodBeforeAdvice
、AfterReturningAdvice
珠漂、ThrowsAdvice
的晚缩。
在每個類型Advice
(通知)都有對應(yīng)的攔截器尾膊,MethodBeforeAdviceInterceptor
、AfterReturningAdviceInterceptor
荞彼、ThrowsAdviceInterceptor
冈敛。
Spring
需要將每個Advice
(通知)都封裝成對應(yīng)的攔截器類型,返回給容器鸣皂,所以需要使用適配器模式對Advice
進行轉(zhuǎn)換抓谴。下面我們看看具體的代碼。
MethodBeforeAdvice類:Adaptee
Adapter類接口:Target
MethodBeforeAdviceAdapter類寞缝,Adapter
DefaultAdvisorAdapterRegistry類癌压,Client
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);
/**
* Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
*/
public DefaultAdvisorAdapterRegistry() {//這里注冊了適配器
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {//這里調(diào)用了適配器的方法
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {//這里調(diào)用了適配器的方法
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}