适配器模式是指将一个类的接口转换为用户期望的另一个接口,使原本接口不兼容的类可以一起工作,属于结构型设计模式。
适配器模式适用于以下几种业务场景:
1.已经存在的类的方法和需求不匹配(方法相同或相似)的情况
2.适配器模式不是软件初始阶段考虑的设计模式,是随着软件的发展,由于不同产品,不同厂家造成功能类似而接口不同的问题的解决方案,有点亡羊补牢的感觉、
下面结合登录逻辑进行示例
首先创建工具类Member类及ResultMsg类
public class Member {
private String username;
private String password;
private String mid;
private String info;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getMid() {
return mid;
}
public void setMid(String mid) {
this.mid = mid;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
public class ResultMsg {
private int code;
private String msg;
private Object data;
public ResultMsg(int code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
假设原来登录逻辑如下
public class SiginService {
/**
* 注册方法
* @param username
* @param password
* @return
*/
public ResultMsg regist(String username,String password) {
return new ResultMsg(200,"注册成功", new Member());
}
/**
* 登录方法
* @param username
* @param password
* @return
*/
public ResultMsg login(String username,String password) {
return new ResultMsg(200,"登录成功", new Member());
}
}
现用适配器模式进行改造 例如下
public class SiginForThirdService extends SiginService {
//QQ登录
public ResultMsg LoginForQQ(String openId) {
return new ResultMsg(200,"登录成功",null);
}
//微信登录
//新浪登录
//Token登录
}
但只用该模式使代码仍有诸多缺陷下面结合工厂模式,单例模式,策略模式等模式对该逻辑进行优化
首先创建登录接口(当然这个接口从原则上来说是可有可无的)
public interface LoginAdapter {
boolean support(Object adapter);
ResultMsg login(String id,Object adapter);
}
创建接口实现
public class LoginForQQAdapter implements LoginAdapter {
@Override
public boolean support(Object adapter) {
return adapter instanceof LoginForQQAdapter;
}
@Override
public ResultMsg login(String id, Object adapter) {
// TODO Auto-generated method stub
return null;
}
}
public class LoginForSinaAdapter implements LoginAdapter {
@Override
public boolean support(Object adapter) {
return adapter instanceof LoginForSinaAdapter;
}
@Override
public ResultMsg login(String id, Object adapter) {
// TODO Auto-generated method stub
return null;
}
}
public class LoginForTelAdapter implements LoginAdapter {
@Override
public boolean support(Object adapter) {
return adapter instanceof LoginForTelAdapter;
}
@Override
public ResultMsg login(String id, Object adapter) {
// TODO Auto-generated method stub
return null;
}
}
创建第三方登录兼容接口
public interface IPassportForThird {
ResultMsg loginForQQ(String id);
ResultMsg loginForSina(String id);
ResultMsg loginForTel(String tel,String code);
}
创建接口实现同时也是适配器模式的实现
public class PassportForThirdAdapter extends SiginService implements IPassportForThird {
@Override
public ResultMsg loginForQQ(String id) {
// TODO Auto-generated method stub
return processLogin(id, LoginForQQAdapter.class);
}
@Override
public ResultMsg loginForSina(String id) {
// TODO Auto-generated method stub
return processLogin(id, LoginForSinaAdapter.class);
}
@Override
public ResultMsg loginForTel(String tel, String code) {
// TODO Auto-generated method stub
return processLogin(tel, LoginForTelAdapter.class);
}
private ResultMsg processLogin(String key,Class extends LoginAdapter> clazz) {
try {
LoginAdapter adapter = clazz.newInstance();
if(adapter.support(adapter)) {
return adapter.login(key, adapter);
}else {
return null;
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return null;
}
}
适配器模式的优缺点
适配器模式的优点:
1.能提高类的透明性和复用性,现有的类会被复用但不需要改变
2.目标类与适配器解耦,可以提高程序的扩展性
3.在很多业务场景下符合开闭原则
适配器模式的缺点
1.在适配器代码的编写过程中需要全面考虑,可能会增加系统的复杂性
2.增加了代码的阅读难度,降低了代码的可读性,过多使用适配器会使代码变得凌乱