前言:边动手,边动脑,才能进步,只动手不动脑,一塌糊涂
定义:
将一个接口转化成用户期望的另一个接口,使原本不兼容的类可以一起工作,属于结构型设计模式。
适用场景:
1.已经存在的类,它的方法和需求不匹配(方法结果相同或相似)
2.适配器模式是随着软件维护,由于不同产品,不同厂商造成功能类似而接口不相同的解决方案
实际案例:
比较旧的软件登录只支持用户名和密码登录,现在在用户名和密码登录的同时多了扣扣登录、微信登录、手机登录等情况,
登录的方式变了,不过登录的结果不会变,同样将登录状态保存到session、redis等缓存中
package com.ns.adapter;
/**
* 通用的返回类
*/
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;
}
}
package com.ns.adapter;
/**
* 旧的登录类
*/
public class OldLogin {
/**
* 注册
*/
public ResultMsg regist(String userName, String password){
System.out.println("注册成功");
return new ResultMsg(200,"注册成功",null);
}
/**
* 登录
*/
public ResultMsg login(String userName, String password){
System.out.println("用户名和密码登录成功");
return new ResultMsg(200,"用户名和密码登录成功",null);
}
}
package com.ns.adapter;
/**
* 扩展新的登录方式接口,只是为了抽象出验证方法与登录方法,用来让其他登录方式实现
*/
public interface ILoginService {
//验证方法,针对使用策略模式做一个简单验证,可以通过其他方式解决
boolean support(Object adapter);
ResultMsg login(String id, Object adapter);
}
package com.ns.adapter;
/**
* QQ登录
*/
public class QQLogin implements ILoginService {
@Override
public boolean support(Object adapter) {
return adapter instanceof QQLogin;
}
@Override
public ResultMsg login(String id, Object adapter) {
System.out.println("通过QQ登录");
return new ResultMsg(200,"QQ登录成功",null);
}
}
package com.ns.adapter;
/**
* 微信登录
*/
public class WechatLogin implements ILoginService {
@Override
public boolean support(Object adapter) {
return adapter instanceof WechatLogin;
}
@Override
public ResultMsg login(String id, Object adapter) {
System.out.println("通过微信登录");
return new ResultMsg(200,"通过微信登录成功",null);
}
}
package com.ns.adapter;
/**
* 手机号登录
*/
public class TelLogin implements ILoginService {
@Override
public boolean support(Object adapter) {
return adapter instanceof TelLogin;
}
@Override
public ResultMsg login(String id, Object adapter) {
System.out.println("通过手机号登录");
return new ResultMsg(200,"通过手机号登录成功",null);
}
}
package com.ns.adapter;
/**
* 其他方式登录接口的集成
* 此接口以及实现类也可以省去,根据不同的登录类型抽象出不同的策略,使用策略模式来达到不同场景的登录需求
*/
public interface LoginForOther {
ResultMsg loginForQQ(String id);
ResultMsg loginForWechat(String id);
ResultMsg loginForTel(String id);
ResultMsg loginForRegist(String userName, String password);
}
package com.ns.adapter;
/**
* 其他方式登录接口的集成实现
* 登录适配器类,通过集成老的登录方式,并实现新的登录方式,保证旧的保留,新的可用
*/
public class LoginForOtherAdapter extends OldLogin implements LoginForOther {
@Override
public ResultMsg loginForQQ(String id) {
return processLogin(id,QQLogin.class);
}
@Override
public ResultMsg loginForWechat(String id) {
return processLogin(id,WechatLogin.class);
}
@Override
public ResultMsg loginForTel(String id) {
return processLogin(id,TelLogin.class);
}
@Override
public ResultMsg loginForRegist(String userName, String password) {
super.regist(userName,password);
return super.login(userName,password);
}
/**
* 简单工厂模式以及策略模式的应用
*/
private ResultMsg processLogin(String key, Class<? extends ILoginService> clazz){
try {
ILoginService loginService = clazz.newInstance();
if(loginService.support(loginService)){
return loginService.login(key,loginService);
}
return null;
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
package com.ns.adapter;
/**
* 测试类
*/
public class TestLogin {
public static void main(String[] args) {
LoginForOther loginForOther = new LoginForOtherAdapter();
loginForOther.loginForTel("1111");
}
}
总结
优点:
1.提高类的透明和应用,现有类复用但不需要改变
2.目标类和适配器类解耦,提高类的可扩展性
缺点:
1.适配器编写过程需要全面考虑,会增加系统的复杂度
2.降低了代码的可读性,使代码更复杂
注:上述案例只是简单说明了适配器模式的应用,代码逻辑方面可以再次应用策略模式进行扩展,可以自己思考下。
最后,希望大家都能学以致用。