适配器模式-第三方登录与设计模式的七七八八
适配器模式
- 应用场景
- 第三方登录-单一适配器
- 第三方登录-多种设计模式
- 适配器模式源码中的体现
应用场景
适配器模式一般是一个软件运维阶段出现的模式,为了兼容不同类,搞一个接口出来,这个接口的作用类似于数据线转换头这种概念,命名一般以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中,就有使用到适配器模式的地方
适配器模式-第三方登录与设计模式的七七八八相关推荐
- 使用cocoaPods一键集成第三方登录(新浪微博,qq,微信)
第三方登录是现在app很常用的功能,而这个功能我已经写过两三次了...每次都写大同小异的代码真的是很痛苦,而且每次都要根据说明去添加那些依赖库,配置linkFlag什么的,完全是体力活,所以一直想把这 ...
- Spring Security OAuth2 优雅的集成短信验证码登录以及第三方登录
基于SpringCloud做微服务架构分布式系统时,OAuth2.0作为认证的业内标准,Spring Security OAuth2也提供了全套的解决方案来支持在Spring Cloud/Spring ...
- android qq第三方登录,Android调用第三方QQ登录代码分享
本文为大家分享了调用QQ登录的相关代码,希望对大家有帮助,减少项目开发的时间,具体内容如下 1.去QQ开放平台注册帐号(http://open.qq.com/),为应用申请QQ的APP_ID , 并下 ...
- sdk没有登录什么意思_不需要接入SDK的第三方登录及分享
讲到第三方登录分享,第一反应大概就是友盟.ShareSDK之类.集成微信.QQ.微博三个平台的话,友盟的SDK有62.9M,ShareSDK的包有74M.如果直接集成最原始的三个平台的SDK,大小总共 ...
- PHP 接入(第三方登录)QQ 登录 OAuth2.0 过程中遇到的坑
前言 绝大多数网站都集成了第三方登录,降低了注册门槛,增强了用户体验.最近看了看 QQ 互联上 QQ 登录的接口文档.接入 QQ 登录的一般流程是这样的:先申请开发者 -> 然后创建应用(拿到一 ...
- 拾人牙慧篇之———QQ微信的第三方登录实现
一.写在前面 关于qq微信登录的原理之流我就不一一赘述了,对应的官网都有,在这里主要是展示我是怎么实现出来的,看了好几个博客,有的是直接复制官网的,有的不知道为什么实现不了.我只能保证我的这个是我实现 ...
- Symfony 使用 hwi/oauth-bundle 实现第三方登录
hwi/oauth-bundle插件官方文档只简单给出了登录示例,实际工作中往往需要对获取到的用户信息进行存库处理.那如何来处理呢,下面给出我在项目中处理步骤希望能帮助到大家. 首先创建hwi/oau ...
- QQ第三方登录报错error=-1
qq 第三方登录报错error=-1 再次实例化qc类.
- Yii2 使用 QQ 和 Weibo 第三方登录源码
我们社区在 yii2-authclient 多次升级后,登录异常.一直想寻求一种通用的方法,尽量不重写 OAuth2, BaseOAuth 以及 OAuthToken 类, 所以本次直接在 initU ...
最新文章
- ubuntu+php+mysql+apache安装配置
- CentOS 5升级Python版本(2.42.7)
- BM算法的shift1表是在所有情况下移动都是最快的吗?
- B01_NumPy Ndarray对象(ndarray内容结构,参数,多维,最小维度,dtype参数)
- 配置Java EE应用程序或“将Bien付诸实践”
- git 忽略__pycache___图解git,用手绘图带你理解git中分支的原理和应用
- 关于kinect的一些想法
- JavaScript之语句
- 高通联机修改IMEI等参数的相关解析
- volatility内存取证
- 服贸会 | 神州信息:5代ModelB@nk伴随银行业科技创新发展
- ogre 学习笔记 - Day 7
- 计算器和计算机有什么不同,计算机和计算器有区别吗?
- EEG-fMRI同步记录的伪影去除法
- java对手机芯片有没有要求_芯片对手机到底有多重要
- vue 配置文件不打包
- elementui 按钮 表单_仿ElementUI实现一个Form表单的实现代码
- new Map()详细介绍 map .set(key,value)map.sizemap.get(key)map.has(key)map.delete(key)map.clear()
- 转载:关于动漫与动画
- 使用xsl实时处理xml文档(Javascript语言)
热门文章
- 华为java 优招面试题_华为面试题及答案
- 扒一扒ThreadLocal原理及应用
- 『Python学习笔记』np.random.rand()函数和np.random.randn()函数
- node版本管理工具nvm
- IDEA使用问题 —— Inspection info 波浪线
- 缅怀钟扬教授,5分钟视频回顾伟大植物学家钟扬对人类的贡献
- 【总结】解决MAPPO(Multi-Agent PPO)问题技巧
- 解析v-if和v-show的区别和使用场景
- maven打包war包
- 吴恩达寄语:6大主题回顾AI圈儿的2020