适配器使用场景
当系统依赖的接口提供了需要的功能,但是接口签名并不是完全匹配时,就可以使用适配器模式,将外部接口桥接到内部系统上。
代码实例
依赖接口
public interface RemoteCallBackA {
void doCallBackA();
}
public interface RemoteCallBackB {
void doCallBackB();
}
业务逻辑
public class BuzLogic {
public void doLogic(Object callBack) { //做完自身业务逻辑后回调外部接口
System.out.println("do business start");
System.out.println("do business end");
if (callBack instanceof RemoteCallBackA) {
((RemoteCallBackA) callBack).doCallBackA();
} else if (callBack instanceof RemoteCallBackB) {
((RemoteCallBackB) callBack).doCallBackB();
}
}
}
自己的业务BuzLogic需要回调2个外部系统的接口,但外部接口签名不通用,只能通过instanceof来进行区分;当增加一个外部系统时,必然会修改BuzLogic的核心功能;违背开闭原则。设计的原则是封装变化的点,这里变化的点是外部系统签名不同,因此可以使用适配器模式封装这一变化。
使用适配器模式的代码
public interface CallBackAdapter {
public void callBack(Object target);
public boolean supports(Object remoteInterface);
}
public class CallBackAdapterA implements CallBackAdapter {
public void callBack(Object target) {
RemoteCallBackA remoteCallBackA = (RemoteCallBackA)target;
remoteCallBackA.doCallBackA();
}
@Override
public boolean supports(Object remoteInterface) {
return remoteInterface instanceof RemoteCallBackA;
}
}
public class CallBackAdapterB implements CallBackAdapter {
@Override
public void callBack(Object target) {
RemoteCallBackB remoteCallBackA = (RemoteCallBackB)target;
remoteCallBackA.doCallBackB();
}
@Override
public boolean supports(Object remoteInterface) {
return remoteInterface instanceof RemoteCallBackB;
}
}
public class BuzLogic {
CallBackAdapter[] callBackAdapterArray = new CallBackAdapter[]{new CallBackAdapterA(),new CallBackAdapterB()};
public void doLogic(Object callBack) {
System.out.println("do business start");
System.out.println("do business end");
CallBackAdapter adapter = getCallBackAdapter(callBack);
adapter.callBack(callBack);
}
private CallBackAdapter getCallBackAdapter(Object callBack) {
for (CallBackAdapter adapter : callBackAdapterArray) {
if (adapter.supports(callBack)) {
return adapter;
}
}
return null;
}
}
之后如果要增加外部系统,只需要添加一个Adapter就可以了,无需修改doLogic代码。
适配器模式引发的思考
抛开具体代码,这个模式带给我们的启发是通过继承和循环替代if/else达到代码的整洁。在扩展功能时由于使用了if/else需要修改业务逻辑,导致违背开闭原则,不便于横向扩展 。适配器模式封装这种变化消除if/else,把每个变化分支放到一个子类中去,在上面的例子中supports和callBack组成一个分支;然后通过父类将所有变化点组织起来,并通过for循环的方式去遍历每个分支;当增加新的分支时,添加一个新的子类而无需修改for循环,达到对新增开发对修改封闭。这种编码的思想应该牢记于心,当复杂业务逻辑使用if/else横向扩展时,就应该通过设计模式封装变化。
另外一种类适配器以MouseAdapter为例,它实现了MouseListener, MouseWheelListener, MouseMotionListener这3个接口,并为所有方法生成了一个空实现方便子类使用。