适配器模式(Adapter)
概述
适配器模式是为了兼容。开发中我们常会遇到这样的场景:老系统运行了很久,为了保持其稳定性,不便再去修改原来的代码,但是又为了兼容新的需求或者标准,我们不得不在系统再去做一些文章(向下兼容)。
穷举法
编码解码、 一拖三充电头、HDMI 转 VGA、 Type-C 转 USB
应用场景
登陆功能的升级
说一个项目开发都会遇到的场景:登陆功能的开发。直接上代码。
最开始只需要用户名和密码(注册和登陆)。
public class SignInService {
/**
* 注册方法
* @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 null;
}
}
随着互联网技术的发展,用户的需求变得多样化。需要新增如下功能:微信登陆、QQ登陆、微博登陆、手机号+验证码登陆。
直接在原类中修改会破环源代码的稳定性,这时我们可以借助适配器模式。
//稳定的方法不去动,直接继承下来
public class SignInForThirdService extends SignInService {
public ResultMsg loginForQQ(String openId){
//1、openId是全局唯一,我们可以把它当做是一个用户名(加长)
//2、密码默认为QQ_EMPTY
//3、注册(在原有系统里面创建一个用户)
//4、调用原来的登录方法
return loginForRegist(openId,null);
}
public ResultMsg loginForWechat(String openId){
return null;
}
public ResultMsg loginForToken(String token){
//通过token拿到用户信息,然后再重新登陆了一次
return null;
}
public ResultMsg loginForTelphone(String telphone,String code){
return null;
}
public ResultMsg loginForRegist(String username,String password){
super.regist(username,password);
return super.login(username,password);
}
}
上述SignInForThirdService 通过继承SignInService 类,在新增功能中直接调用父类中的regist()和login()。
当然我们也可以通过注入来实现,而非继承。
测试类
public class SignInForThirdServiceTest {
public static void main(String[] args) {
SignInForThirdService service = new SignInForThirdService();
//不改变原来的代码,也要能够兼容新的需求
//还可以再加一层策略模式
service.loginForQQ("sdfgdgfwresdf9123sdf");
}
}
Spring AOP中的通知
Spring AOP 模块对 BeforeAdvice、 AfterAdvice、 ThrowsAdvice 三种通知类型的支持实际上是借助适配器模式来实现的, 这样的好处是使得框架允许用户向框架中加入自己想要支持的任何一种通知类型, 上述三种通知类型是 Spring AOP 模块定义的, 它们是 AOP 联盟定义的 Advice 的子类型。
总结
适配器模式注重兼容、转换。适配者与被适配者之间没有层级关系,也没有必然联系。