一、适配器模式的应用场景  

  适配器模式(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”。

四、适配器模式的优缺点

  优点:

  • 能提高类的透明性和复用性,现有的类会被复用但不需要改变。
  • 目标类和适配器类解耦,可以提高程序的扩展性。
  • 在很多业务场景中符合开闭原则。

  缺点:

  • 在适配器代码编写过程中需要进行全面考虑,可能会增加系统复杂度。
  • 增加代码阅读难度,过多使用适配器会使系统代码变得凌乱。

  

Spring中常见的设计模式——适配器模式的更多相关文章

  1. Spring中常见的设计模式——代理模式

    一.代理模式的应用场景 生活中的中介,黄牛,等一系列帮助甲方做事的行为,都是代理模式的体现.代理模式(Proxy Pattern)是指为题对象提供一种代理,以控制对这个对象的访问.代理对象在客户端和目 ...

  2. Spring中常见的设计模式——单例模式

    一.单例模式的应用场景 单例模式(singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点.J2EE中的ServletContext,ServletCon ...

  3. Spring中常见的设计模式——委派模式

    一.委派模式的定义及应用场景 委派模式(Delegate Pattern)的基本作用是负责任务的调用和分配,跟代理模式很像,可以看做特殊情况下的静态的全权代理,但是代理模式注重过程,而委派模式注重结果 ...

  4. Spring中常见的设计模式——策略模式

    策略模式(Strategy Pattern) 一.策略模式的应用场景 策略模式的应用场景如下: 系统中有很多类,而他们的区别仅仅在于行为不同. 一个系统需要动态的在集中算法中选择一种 二.用策略模式实 ...

  5. Spring中常见的设计模式——工厂模式

    一.简单工厂模式 简单工厂模式(Simple Factory Pattern)由一个工厂对象决定创建哪一种产品类的实例,简单工厂模式适用于工厂类负责创建对象较少的情况,且客户端只需要传入工厂类的参数, ...

  6. Spring中常见的设计模式——原型模式

    1.原型模式应用场景 当遇到大量耗费劳动力的 get,set赋值场景时,如下: public class SetGetParam { public void setParam(UserDto user ...

  7. Spring中常见的设计模式——模板模式

    一.模板模式的应用场景 模板模式又叫模板方法模式(Template Method Pattern),指定义一个算法的骨架,并允许自雷为一个或者多个步骤提供实现.模板模式使得子类可以在不改变算法结果的情 ...

  8. 设计模式:JDK和Spring中常见的设计模式

    设计模式 总结 类 工厂模式 封装创建过程,只对结果负责 BeanFactory.Calender 单例模式 全局唯一 ApplicationContext.Calender 原型模式 多重影分身之术 ...

  9. spring 中常用的设计模式

    一. Spring 中常见的设计模式 工厂模式 : BeanFactory 装饰器模式: BeanWrapper 代理模式: AopProxy 单例模式: ApplicationContext 委派模 ...

随机推荐

  1. 2013-10-6 datagridview实现换行并自动设置行高

    datagridview设置换行,如下,文本设置\r\n即可换行 dv4.DefaultCellStyle.WrapMode = DataGridViewTriState.True; dv4.Auto ...

  2. 2018-8-10-win10-uwp-后台获取资源

    title author date CreateTime categories win10 uwp 后台获取资源 lindexi 2018-08-10 19:17:19 +0800 2018-2-13 ...

  3. H3C NAPT配置举例

  4. Java中方法的格式

    [修饰符] 返回值类型 方法名([参数类型 形式参数1,参数类型 形式参数2,……]) {             执行语句;     [return 返回值;]//需要的话 } 参数列表(参数的类型 ...

  5. Mysql5.7在忘记密码的情况下如何修改密码?

    1.停止服务 2.mysqld --skip-grant-tables 3.回车之后就不要动了,再新打开一个命令提示符窗口,同样进入mysql的安装目录下, 输入:mysql -u root -p 密 ...

  6. P1020 从大到小排序

    题目描述 给你n个整数,请你按照从大到小的顺序输出它们. 输入格式 输入的第一行包含一个整数 \(n(1 \le n \le 10^3)\) ,用于表示元素的个数. 输入的第二行包含 \(n\) 个整 ...

  7. P1006 输出第二个整数

    题目描述 输入三个整数,整数之间由一个空格分隔,整数是32位有符号整数.把第二个输入的整数输出. 输入格式 输入三个整数,整数之间由一个空格分隔,整数是32位有符号整数. 输出格式 输出输入的三个整数 ...

  8. js求1到任意数之间的所有质数

    何为质数: 只能被1 和 自身 整除的数; 方法: 利用js中求模, 看是否有余数. ---> 3%2 = 1; 5%2 = 3......... 代码如下: function test (n) ...

  9. Weblogic/WAS之Full GC监控与计算

    在网上看到关于内存回收机制,同大家一起分析探讨.堆内存划分为Eden.Survivor 和 Tenured/Old 空间,如下图所示: Minor GC 会清理年轻代的内存,Major GC 是清理老 ...

  10. mapstatetoprops更新state但props不更新渲染的问题

    通过react-redux和redux实现react组件之间的通信,reducer.action.store都编写正确,mapDispatchToProps也能正确传值.唯独mapStateToPro ...