很多童鞋經常背誦抽象類和接口的區別,使用場景,但並沒有深入瞭解什麼時候使用他們,或者使用哪個更好,本文舉一小例,並不一定完全正確,歡迎讀者吐槽;
我們看一個銀行借款的領子,中國人民銀行管理並監督所有的銀行,它制定了一個規範,所有的銀行在進行借款時都必須遵守這個規範(基本接口);
Version~0.1.0:
中國人民銀行定義了一個操作接口:
package GoodDesignPattern;
import java.util.Map;
public interface BankLoan {
/**
* 銀行借款操作
* 每個公司都需要實現該方法,並針對自己公司員工的情況進行特殊操作,
* 比如判斷該員工是否有資格,能借款多少等等
* @return
*/
public Map<String, String> loanOperation(String userId);
}
所有的銀行都必須遵守這個接口,進行具體的實現:
package GoodDesignPattern;
import java.util.HashMap;
import java.util.Map;
public class ABC implements BankLoan {
@Override
public Map<String, String> loanOperation(String userId) {
//所有銀行借款必須的校驗
if(userId==null || userId.isEmpty()){
System.out.println("userId爲空!");
return null;
}
//所有銀行借款必須的校驗
if(userId.length()!=32){
System.out.println("userId格式錯誤,應該爲32位!"+userId);
return null;
}
//所有銀行借款必須的校驗
if(!queryUserExist(userId)){
System.out.println("用戶不存在:"+userId);
return null;
}
//所有銀行借款必須的校驗
if(!queryUserIllegal(userId)){
System.out.println("用戶沒有資格進行借款:"+userId);
return null;
}
//業務邏輯
Map<String, String> map = getResultMap(userId);
return map;
}
//根據數據庫查詢是否存在,根據自己公司的用戶表查詢
public boolean queryUserExist(String userId){
return true; //return false;
}
//根據數據庫查詢數據查詢判斷
public boolean queryUserIllegal(String userId){
return true; //return false;
}
//根據數據庫查詢相關信息
public Map<String, String> getResultMap(String userId){
Map<String, String> map = new HashMap<String, String>();
map.put("name", "詹姆斯"); //此處爲了方便直接寫死
map.put("amount", "100000"); //應根據userId,在系統進行一系列判斷計算,得出能借款金額,此處爲了方便直接寫死
map.put("rankLevel", "A"); //應根據userId,在系統進行一系列判斷計算,得出用戶等級,此處爲了方便直接寫死
//.....其它一些列操作
return map;
}
}
package GoodDesignPattern;
import java.util.HashMap;
import java.util.Map;
public class ICBC implements BankLoan {
@Override
public Map<String, String> loanOperation(String userId) {
//所有銀行借款必須的校驗
if(userId==null || userId.isEmpty()){
System.out.println("userId爲空!");
return null;
}
//所有銀行借款必須的校驗
if(userId.length()!=32){
System.out.println("userId格式錯誤,應該爲32位!"+userId);
return null;
}
//所有銀行借款必須的校驗
if(!queryUserExist(userId)){
System.out.println("用戶不存在:"+userId);
return null;
}
//所有銀行借款必須的校驗
if(!queryUserIllegal(userId)){
System.out.println("用戶沒有資格進行借款:"+userId);
return null;
}
//業務邏輯
Map<String, String> map = getResultMap(userId);
return map;
}
//根據數據庫查詢是否存在,根據自己公司的用戶表查詢
public boolean queryUserExist(String userId){
return true; //return false;
}
//根據數據庫查詢數據查詢判斷
public boolean queryUserIllegal(String userId){
return true; //return false;
}
//根據數據庫查詢相關信息
public Map<String, String> getResultMap(String userId){
Map<String, String> map = new HashMap<String, String>();
map.put("amount", "100000"); //應根據userId,在系統進行一系列判斷計算,得出能借款金額,此處爲了方便直接寫死
map.put("rankLevel", "A"); //應根據userId,在系統進行一系列判斷計算,得出用戶等級,此處爲了方便直接寫死
//.....其它一些列操作
return map;
}
}
我們發現,每當一家銀行做此操作時,都會做一些校驗,並且他們都是類似的,這不僅繁瑣,而且有些銀行容易遺漏一些校驗操作;雖然校驗的邏輯大同小異,但是每個銀行都可能自己定義自己的方法名、判斷自己的業務邏輯,這樣的開發低效且中國人民銀行不方便管理,爲此,人行需要調整自己的規範,統一各個銀行的行爲;
Version~0.2.0:
中國人民銀行修改自己的規範:
之前的接口不變,新增一個抽象類:
package GoodDesignPattern;
import java.util.Map;
public abstract class CommonOpretion {
public Map<String, String> loanOperation(String userId) {
//所有銀行借款必須的校驗
if(userId==null || userId.isEmpty()){
System.out.println("userId爲空!");
return null;
}
//所有銀行借款必須的校驗
if(userId.length()!=32){
System.out.println("userId格式錯誤,應該爲32位!"+userId);
return null;
}
//所有銀行借款必須的校驗
if(!queryUserExist(userId)){
System.out.println("用戶不存在:"+userId);
return null;
}
//所有銀行借款必須的校驗
if(!queryUserIllegal(userId)){
System.out.println("用戶沒有資格進行借款:"+userId);
return null;
}
//業務邏輯
Map<String, String> map = getResultMap(userId);
return map;
}
//根據數據庫查詢是否存在,根據自己公司的用戶表查詢
protected abstract boolean queryUserExist(String userId);
//根據數據庫查詢數據查詢判斷
protected abstract boolean queryUserIllegal(String userId);
//根據數據庫查詢相關信息
protected abstract Map<String, String> getResultMap(String userId);
}
看看這個抽象類的邏輯,你可以看出來,把所有的公共邏輯都寫在裏面,具體的業務操作方法是抽象的,由具體的銀行去實現即可,看下銀行的實現:
package GoodDesignPattern;
import java.util.HashMap;
import java.util.Map;
public class ABC extends CommonOpretion implements BankLoan {
//根據數據庫查詢是否存在,根據自己公司的用戶表查詢
@Override
public boolean queryUserExist(String userId){
return true; //return false;
}
//根據數據庫查詢數據查詢判斷
@Override
public boolean queryUserIllegal(String userId){
return true; //return false;
}
//根據數據庫查詢相關信息
@Override
public Map<String, String> getResultMap(String userId){
Map<String, String> map = new HashMap<String, String>();
map.put("name", "詹姆斯"); //此處爲了方便直接寫死
map.put("amount", "100000"); //應根據userId,在系統進行一系列判斷計算,得出能借款金額,此處爲了方便直接寫死
map.put("rankLevel", "A"); //應根據userId,在系統進行一系列判斷計算,得出用戶等級,此處爲了方便直接寫死
//.....其它一些列操作
return map;
}
}
package GoodDesignPattern;
import java.util.HashMap;
import java.util.Map;
public class ICBC extends CommonOpretion implements BankLoan {
//根據數據庫查詢是否存在,根據自己公司的用戶表查詢
@Override
public boolean queryUserExist(String userId){
return true; //return false;
}
//根據數據庫查詢數據查詢判斷
@Override
public boolean queryUserIllegal(String userId){
return true; //return false;
}
//根據數據庫查詢相關信息
@Override
public Map<String, String> getResultMap(String userId){
Map<String, String> map = new HashMap<String, String>();
map.put("amount", "100000"); //應根據userId,在系統進行一系列判斷計算,得出能借款金額,此處爲了方便直接寫死
map.put("rankLevel", "A"); //應根據userId,在系統進行一系列判斷計算,得出用戶等級,此處爲了方便直接寫死
//.....其它一些列操作
return map;
}
}
每個銀行只要繼承這個抽象類,並實現對應的業務邏輯方法即可,一些校驗都統一放入抽象類中判斷,這樣,每個銀行的實現邏輯清晰、規範、不會遺漏校驗,當然如果抽象類中的某些抽象方法,有些銀行不想做具體實現,可以默認返回,當然這是一個缺陷,歡迎讀者提出更好的解決方案。
這個時候每個銀行又要實現抽象類,又要實現接口,他們感覺很麻煩且沒有必要,這個時候中國銀行又進行調整:
Version~0.3.0:
頂層接口還是不變,抽象類修改:由抽象類實現接口
package GoodDesignPattern;
import java.util.Map;
public abstract class CommonOpretion implements BankLoan{
@Override
public Map<String, String> loanOperation(String userId) {
//所有銀行借款必須的校驗
if(userId==null || userId.isEmpty()){
System.out.println("userId爲空!");
return null;
}
//所有銀行借款必須的校驗
if(userId.length()!=32){
System.out.println("userId格式錯誤,應該爲32位!"+userId);
return null;
}
//所有銀行借款必須的校驗
if(!queryUserExist(userId)){
System.out.println("用戶不存在:"+userId);
return null;
}
//所有銀行借款必須的校驗
if(!queryUserIllegal(userId)){
System.out.println("用戶沒有資格進行借款:"+userId);
return null;
}
//業務邏輯
Map<String, String> map = getResultMap(userId);
return map;
}
//根據數據庫查詢是否存在,根據自己公司的用戶表查詢
protected abstract boolean queryUserExist(String userId);
//根據數據庫查詢數據查詢判斷
protected abstract boolean queryUserIllegal(String userId);
//根據數據庫查詢相關信息
protected abstract Map<String, String> getResultMap(String userId);
}
具體銀行不再需要實現接口:
package GoodDesignPattern;
import java.util.HashMap;
import java.util.Map;
public class ABC extends CommonOpretion {
//根據數據庫查詢是否存在,根據自己公司的用戶表查詢
@Override
public boolean queryUserExist(String userId){
return true; //return false;
}
//根據數據庫查詢數據查詢判斷
@Override
public boolean queryUserIllegal(String userId){
return true; //return false;
}
//根據數據庫查詢相關信息
@Override
public Map<String, String> getResultMap(String userId){
Map<String, String> map = new HashMap<String, String>();
map.put("name", "詹姆斯"); //此處爲了方便直接寫死
map.put("amount", "100000"); //應根據userId,在系統進行一系列判斷計算,得出能借款金額,此處爲了方便直接寫死
map.put("rankLevel", "A"); //應根據userId,在系統進行一系列判斷計算,得出用戶等級,此處爲了方便直接寫死
//.....其它一些列操作
return map;
}
}
到此一個體現接口和抽象類結合使用的簡單例子就說完了,謝謝~