适配器模式

  • 应用场景
  • 第三方登录-单一适配器
  • 第三方登录-多种设计模式
  • 适配器模式源码中的体现

应用场景

适配器模式一般是一个软件运维阶段出现的模式,为了兼容不同类,搞一个接口出来,这个接口的作用类似于数据线转换头这种概念,命名一般以xxxxAdapter这样的。
比如我们常见的第三方登录,在系统一开始设计的时候,可能只有用户名密码登陆,后来随着qq、微信、手机登陆的普及,登陆方式也多了起来,这个时候就需要适配器模式了,在不改变原来登陆逻辑的基础上,与新的三方登陆做一个适配。

第三方登录-单一适配器

我们先看第一阶段的代码,假如没有第三方登录的原本的实现逻辑是下面这样的

/*** 系统原本的登陆逻辑*/
public class SiginService {/*** 注册*/public ResultMsg regist(String username, String password) {// 经过一系列的注册逻辑,比如验证用户名是否已存在Member member = new Member();member.setUsername(username);member.setPassword(password);return new ResultMsg(200, "注册成功", member);}/*** 登录*/public ResultMsg login(String username, String password) {// 经过一系列的登陆逻辑,比如验证用户名密码正确Member member = new Member();member.setUsername(username);member.setPassword(password);return new ResultMsg(200, "登录成功", member);}}
/*** 用户*/
public class Member {private String username;private String password;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 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;}
}
  • 这里的三方适配逻辑只是一个例子,实际的实现可能有多种,比如qq登录就有跳转qq授权、扫码、qq账号密码登录等几种方式。具体的实现可能是通过token授权、或者是绑定qq账号的时候就绑定了一些雪花ID什么的,但是我们重点是设计模式的结构,不是具体的实现。所以这里简单假设一适配的逻辑即可

然后现在我们的业务有了兼容第三方-QQ登录的需求,就需要一个适配器了

/*** 第三方登录适配器*/
public class SinginForThirdAdapter extends SiginService {public ResultMsg loginForQQ(String qqName,String qqPassword) {// 1.0 假设QQ登录独有的适配逻辑,是通过qq账号密码加个qq后缀得到userName和passwordString userName = qqName + "qq";String password = qqPassword + "qq";// 2.0 调用原本的登录逻辑return super.login(userName, password);}

其实适配器模式就是上面这么简单,单纯的适配器模式的话到这里已经够了。
但是实际业务场景中不会出现这么简单单一的需求,我们要考虑的全面一点,比如日后万一业务又需要支持微信怎么办、需要支持手机登录怎么办。所以往往是多种设计模式结合起来,灵活运用的。

第三方登录-多种设计模式

如果我们现在要支持微信、手机登录之类的,对上面的代码做如下这样的修改,也是可以用的。但是很显然违背了我们的开闭原则,不利于拓展,耦合性太高了

public class SinginForThirdAdapter extends SiginService {public ResultMsg loginForQQ(String qqName,String qqPassword) {// 1.0 假设QQ登录独有的适配逻辑,是通过qq账号密码得到userName和passwordString userName = qqName + "qq";String password = qqPassword + "qq";// 2.0 调用原本的登录逻辑return super.login(userName, password);}public ResultMsg loginForWechat(String openId) {dosomething....}public ResultMsg loginForTelphone(String telphone, String code) {dosomething....}
}

这里其实很容易想到另一个设计模式-策略模式,一个功能的实现对应多种策略,如果有通用的实现逻辑,我们还可以引入类似模板方法模式的概念,把策略模式的父类从接口变成抽象类。如果里面的对象创建逻辑略复杂可优化的话,还可以考虑单例模式(一般较少用到)、几种工厂模式(较多用到)、原型模式这些创建型模式。

/*** 结合策略模式、工厂模式、适配器模式*/
public class PassportForThirdAdapter extends SiginService implements IPassportForThird {public ResultMsg loginForQQ(String id) {return processLogin(id,LoginForQQAdapter.class);}public ResultMsg loginForWechat(String id) {return processLogin(id,LoginForWechatAdapter.class);}public ResultMsg loginForTelphone(String telphone, String code) {return processLogin(telphone,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);}}catch (Exception e){e.printStackTrace();}return null;}
}
/*** 方便拓展*/
public interface IPassportForThird {/*** QQ登录* @param id* @return*/ResultMsg loginForQQ(String id);/*** 微信登录* @param id* @return*/ResultMsg loginForWechat(String id);/*** 手机号登录* @param telphone* @param code* @return*/ResultMsg loginForTelphone(String telphone, String code);
}
/*** 在适配器里面,这个接口是可有可无,不要跟模板模式混淆* 模板模式一定是抽象类,而这里仅仅只是一个接口*/
public interface LoginAdapter {/*** 判断适配器是否适配*/boolean support(Object adapter);ResultMsg login(String id,Object adapter);
}
/*** qq登录适配器*/
public class LoginForQQAdapter implements LoginAdapter {public boolean support(Object adapter) {return adapter instanceof LoginForQQAdapter;}public ResultMsg login(String id, Object adapter) {// 1.0 QQ登录独有的适配逻辑// 2.0 调用原本的登录逻辑}
}
/*** 手机登录适配器*/
public class LoginForTelAdapter implements LoginAdapter {public boolean support(Object adapter) {return adapter instanceof LoginForTelAdapter;}public ResultMsg login(String id, Object adapter) {return null;}
}
/*** 微信登录适配器*/
public class LoginForWechatAdapter implements LoginAdapter {public boolean support(Object adapter) {return adapter instanceof LoginForWechatAdapter;}public ResultMsg login(String id, Object adapter) {return null;}
}

当然,上面的结构还不是最佳的,随着我们具体逻辑的注入,可优化可调整的地方会更多,需要灵活一点。

适配器模式源码中的体现

其实只要在源码中找Adapter结尾的就好了…
比如前面学习委派模式的时候,DispatcherServlet中,就有使用到适配器模式的地方

适配器模式-第三方登录与设计模式的七七八八相关推荐

  1. 使用cocoaPods一键集成第三方登录(新浪微博,qq,微信)

    第三方登录是现在app很常用的功能,而这个功能我已经写过两三次了...每次都写大同小异的代码真的是很痛苦,而且每次都要根据说明去添加那些依赖库,配置linkFlag什么的,完全是体力活,所以一直想把这 ...

  2. Spring Security OAuth2 优雅的集成短信验证码登录以及第三方登录

    基于SpringCloud做微服务架构分布式系统时,OAuth2.0作为认证的业内标准,Spring Security OAuth2也提供了全套的解决方案来支持在Spring Cloud/Spring ...

  3. android qq第三方登录,Android调用第三方QQ登录代码分享

    本文为大家分享了调用QQ登录的相关代码,希望对大家有帮助,减少项目开发的时间,具体内容如下 1.去QQ开放平台注册帐号(http://open.qq.com/),为应用申请QQ的APP_ID , 并下 ...

  4. sdk没有登录什么意思_不需要接入SDK的第三方登录及分享

    讲到第三方登录分享,第一反应大概就是友盟.ShareSDK之类.集成微信.QQ.微博三个平台的话,友盟的SDK有62.9M,ShareSDK的包有74M.如果直接集成最原始的三个平台的SDK,大小总共 ...

  5. PHP 接入(第三方登录)QQ 登录 OAuth2.0 过程中遇到的坑

    前言 绝大多数网站都集成了第三方登录,降低了注册门槛,增强了用户体验.最近看了看 QQ 互联上 QQ 登录的接口文档.接入 QQ 登录的一般流程是这样的:先申请开发者 -> 然后创建应用(拿到一 ...

  6. 拾人牙慧篇之———QQ微信的第三方登录实现

    一.写在前面 关于qq微信登录的原理之流我就不一一赘述了,对应的官网都有,在这里主要是展示我是怎么实现出来的,看了好几个博客,有的是直接复制官网的,有的不知道为什么实现不了.我只能保证我的这个是我实现 ...

  7. Symfony 使用 hwi/oauth-bundle 实现第三方登录

    hwi/oauth-bundle插件官方文档只简单给出了登录示例,实际工作中往往需要对获取到的用户信息进行存库处理.那如何来处理呢,下面给出我在项目中处理步骤希望能帮助到大家. 首先创建hwi/oau ...

  8. QQ第三方登录报错error=-1

    qq 第三方登录报错error=-1 再次实例化qc类.

  9. Yii2 使用 QQ 和 Weibo 第三方登录源码

    我们社区在 yii2-authclient 多次升级后,登录异常.一直想寻求一种通用的方法,尽量不重写 OAuth2, BaseOAuth 以及 OAuthToken 类, 所以本次直接在 initU ...

最新文章

  1. ubuntu+php+mysql+apache安装配置
  2. CentOS 5升级Python版本(2.42.7)
  3. BM算法的shift1表是在所有情况下移动都是最快的吗?
  4. B01_NumPy Ndarray对象(ndarray内容结构,参数,多维,最小维度,dtype参数)
  5. 配置Java EE应用程序或“将Bien付诸实践”
  6. git 忽略__pycache___图解git,用手绘图带你理解git中分支的原理和应用
  7. 关于kinect的一些想法
  8. JavaScript之语句
  9. 高通联机修改IMEI等参数的相关解析
  10. volatility内存取证
  11. 服贸会 | 神州信息:5代ModelB@nk伴随银行业科技创新发展
  12. ogre 学习笔记 - Day 7
  13. 计算器和计算机有什么不同,计算机和计算器有区别吗?
  14. EEG-fMRI同步记录的伪影去除法
  15. java对手机芯片有没有要求_芯片对手机到底有多重要
  16. vue 配置文件不打包
  17. elementui 按钮 表单_仿ElementUI实现一个Form表单的实现代码
  18. new Map()详细介绍 map .set(key,value)map.sizemap.get(key)map.has(key)map.delete(key)map.clear()
  19. 转载:关于动漫与动画
  20. 使用xsl实时处理xml文档(Javascript语言)

热门文章

  1. 华为java 优招面试题_华为面试题及答案
  2. 扒一扒ThreadLocal原理及应用
  3. 『Python学习笔记』np.random.rand()函数和np.random.randn()函数
  4. node版本管理工具nvm
  5. IDEA使用问题 —— Inspection info 波浪线
  6. 缅怀钟扬教授,5分钟视频回顾伟大植物学家钟扬对人类的贡献
  7. 【总结】解决MAPPO(Multi-Agent PPO)问题技巧
  8. 解析v-if和v-show的区别和使用场景
  9. maven打包war包
  10. 吴恩达寄语:6大主题回顾AI圈儿的2020