抽象類和接口 應用場景

很多童鞋經常背誦抽象類和接口的區別,使用場景,但並沒有深入瞭解什麼時候使用他們,或者使用哪個更好,本文舉一小例,並不一定完全正確,歡迎讀者吐槽;


我們看一個銀行借款的領子,中國人民銀行管理並監督所有的銀行,它制定了一個規範,所有的銀行在進行借款時都必須遵守這個規範(基本接口);

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;

	}
	

}
到此一個體現接口和抽象類結合使用的簡單例子就說完了,謝謝~



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章