很多童鞋经常背诵抽象类和接口的区别,使用场景,但并没有深入了解什么时候使用他们,或者使用哪个更好,本文举一小例,并不一定完全正确,欢迎读者吐槽;
我们看一个银行借款的领子,中国人民银行管理并监督所有的银行,它制定了一个规范,所有的银行在进行借款时都必须遵守这个规范(基本接口);
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:
中国人民银行修改自己的规范:
扫描二维码关注公众号,回复:
9233461 查看本文章
之前的接口不变,新增一个抽象类:
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;
}
}
到此一个体现接口和抽象类结合使用的简单例子就说完了,谢谢~