抽象类和接口 应用场景

很多童鞋经常背诵抽象类和接口的区别,使用场景,但并没有深入了解什么时候使用他们,或者使用哪个更好,本文举一小例,并不一定完全正确,欢迎读者吐槽;


我们看一个银行借款的领子,中国人民银行管理并监督所有的银行,它制定了一个规范,所有的银行在进行借款时都必须遵守这个规范(基本接口);

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;

	}
	

}
到此一个体现接口和抽象类结合使用的简单例子就说完了,谢谢~



发布了142 篇原创文章 · 获赞 345 · 访问量 45万+

猜你喜欢

转载自blog.csdn.net/zhengchao1991/article/details/74331428