Spring中常見的設計模式——介面卡模式
阿新 • • 發佈:2020-01-14
一、介面卡模式的應用場景
介面卡模式(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”。
四、介面卡模式的優缺點
優點:
- 能提高類的透明性和複用性,現有的類會被複用但不需要改變。
- 目標類和介面卡類解耦,可以提高程式的擴充套件性。
- 在很多業務場景中符合開閉原則。
缺點:
- 在介面卡程式碼編寫過程中需要進行全面考慮,可能會增加系統複雜度。
- 增加程式碼閱讀難度,過多使用介面卡會使系統程式碼變得凌亂。