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