一, 适配器模式的应用场景
适配器模式 (Adapter Pattern) 是指将一个类的接口转换成用户期待的另一个接口, 使原本接口不兼容的类可以一起工作, 属于构造设计模式.
适配器适用于以下几种业务场景:
已经存在的类的方法和需求不匹配 (方法结果相同或相似) 的情况.
适配器模式不是软件初始阶段应该考虑的设计模式, 是随着软件的开发, 由于不同产品, 不同厂家造成功能类似而接口不同的问题的解决方案, 有点亡羊补牢的感觉.
二, 重构第三方登录自由适配的业务场景
将原来的单一支持用户名和密码登录, 扩展为可以支持微信和手机登录.
创建统一返回结果 ResultMsg:
- @Data
- public class ResultMsg {
- private Integer code;
- private String msg;
- private Object data;
- public ResultMsg(Integer code, String msg, Object data) {
- this.code = code;
- this.data = data;
- this.msg = msg;
- }
- }
老系统登录代码如下:
- public class SignInService {
- public ResultMsg regist(String userName, String passWord) {
- return new ResultMsg(200, "注册成功", new Member());
- }
- public ResultMsg login(String userName, String passWord) {
- return null;
- }
- }
为了遵循开闭原则, 我们不修改老系统代码, 下面是 Member 类:
- @Data
- public class Member {
- private String userName;
- private String passWord;
- private String mid;
- private String info;
- }
我们优雅的根据不同登录方式创建不同的 "Adapter", 首先创建 LoginAdapter:
- public interface LoginAdapter {
- boolean support(Object adapter);
- ResultMsg login(String id, Object adapter);
- }
手机登录:
- public class LoginForTelAdapter implements LoginAdapter {
- @Override
- public boolean support(Object adapter) {
- return adapter instanceof LoginForTelAdapter;
- }
- @Override
- public ResultMsg login(String id, Object adapter) {
- return null;
- }
- }
微信登录:
- public class LoginForWechatAdapter implements LoginAdapter {
- @Override
- public boolean support(Object adapter) {
- return adapter instanceof LoginForWechatAdapter;
- }
- @Override
- public ResultMsg login(String id, Object adapter) {
- return null;
- }
- }
接着, 创建第三方登录兼容接口 IPassportForThid:
- public interface IPassportForThird {
- ResultMsg loginForTel(String telephone, String code);
- ResultMsg loginForWechat(String id);
- ResultMsg loginForResist(String userName, String passWord);
- }
实现兼容 PassportForThirdAdapter:
- public class PassportForThirdAdapter extends SignInService implements IPassportForThird {
- @Override
- public ResultMsg loginForTel(String telephone, String code) {
- return null;
- }
- @Override
- public ResultMsg loginForWechat(String id) {
- return null;
- }
- @Override
- public ResultMsg loginForResist(String userName, String passWord) {
- super.regist(userName, passWord);
- return super.login(userName, passWord);
- }
- // 这里使用简单工厂及策略模式
- private ResultMsg proCSSLogin(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;
- }
- }
前面每个适配器都加上了 support()方法, 用来判断箭筒. support()方法的参数也是 Object 类型, 而 support()来自接口. 适配器并不依赖接口, 我们使用接口只是为了代码规范.
三, 适配器模式在源码中的体现
Spring 中的 AOP 中 AdvisorAdapter 类, 它有三个实现: MethodBeforAdviceAdapter,AfterReturnningAdviceAdapter,ThrowsAdviceAdapter.
先看顶层接口 AdviceAdapter 的源代码:
- public interface AdvisorAdapter {
- boolean supportsAdvice(Advice var1);
- MethodInterceptor getInterceptor(Advisor var1);
- }
再看 MethodBeforAdviceAdapter:
- public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
- private final MethodBeforeAdvice advice;
- public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
- Assert.notNull(advice, "Advice must not be null");
- this.advice = advice;
- }
- public Object invoke(MethodInvocation mi) throws Throwable {
- this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
- return mi.proceed();
- }
- }
其他两个类就不看了. Spring 会根据不同的 AOP 配置来使用对应的 "Advice", 与策略模式不同的是, 一个方法可以同时拥有多个 "Advice".
四, 适配器模式的优缺点
优点:
能提高类的透明性和复用性, 现有的类会被复用但不需要改变.
目标类和适配器类解耦, 可以提高程序的扩展性.
在很多业务场景中符合开闭原则.
缺点:
在适配器代码编写过程中需要进行全面考虑, 可能会增加系统复杂度.
增加代码阅读难度, 过多使用适配器会使系统代码变得凌乱.
来源: https://www.cnblogs.com/xcgShare/p/12190642.html