面试题:抽象类和接口的区别?

1.使用场景不同:

抽象类的使用场景是,当几个类有相同代码时,我们可以将相同代码抽取出来,实现不同的代码设置成抽象接口,让这几个类去继承这个抽象类,通过实现抽象接口来实现不同逻辑的定制化开发。 这样做的好处:1.当公有代码需要修改时,只需要修改父类就可以,不需要每个子类都去修改,这样防止漏修改子类代码而导致代码逻辑错误 2.代码简洁,可读性高 3.减少测试

接口定义的是一种行为规范,一个逻辑功能的主流程定了,分支有多种不同的实现,可以写一个接口,通过接口把主流程逻辑实现,如果有不同实现,实现这个接口即可。 这个是中间件和提取共有代码的基础,如果没有多态,很多共有代码就提取不出来。这样做的好处:1.这是抽取很多公有逻辑的基础,如果没有接口很多中间件代码也抽取不出来 2.减少测试

2.一个类只能继承一个抽象类,可以实现多个接口

3.抽象类里面有方法的实现,接口不可以有方法实现(jdk8可以了,default)

抽象类:

看一下如下代码:

招聘外卖员有如下流程 ,从外卖库里面查询出应聘的外卖员 ,然后进行身份证验证, 是否有犯罪记录验证,验证通过后,培训外卖员,培训完成后让外卖员等待上岗,上岗了再将数据同步到外卖表。

慢慢的公司扩展了新业务,开放了跑腿服务。 招聘跑腿员有如下流程,从跑腿库里面查询出应聘的跑腿人员 ,然后进行身份证验证 ,是否有犯罪记录验证,验证通过后,培训跑腿人员,培训完成后让跑腿人员等待上岗,上岗了再将数据同步到跑腿表。

这2个类的代码有如下特点 除了数据源不一样外,其他所有流程都是一样的,慢慢的因为一些规定,需要对培训人员培训交通规则,代码改成如下形式:

private void train(WaiMai takeout) {

System.out.println("需要进行安全培训");

}

一个业务变更修改了2处代码,而且这2处的代码一模一样。现在只有2处修改,你可能不会修改错或者漏掉修改代码。慢慢的公司业务场景越来越多 ,其他人员招募也越来越多,比如已经有10个场景的招募 , 因为一些原因 ,需要在培训的时候,再添加摩托车让行人规范讲解。 那需要修改10处代码,你能保证你能把这10处代码都修改正确吗,查看代码特点 除了查询招募人员和上岗的时候需要同步上岗人员不一样外,其他所有流程都一样 ,那将代码改成如下形式:

公有逻辑抽取出来,抽取到RecruitService中,子类不同的实现设计成抽象方法,子类实现父类的抽象方法来实现子类的定制化开发。

这么写的好处:

1.当需要修改公有逻辑时,我们只需要修改父类的代码,这样由n处修改变成了1处修改

2.代码简洁

3.减少测试。不抽取父类代码还是按照之前代码的书写方法,我们现在需要对货运人员进行招聘,包含查询货运司机,身份证等等和前面相同的逻辑,然后上岗将数据同步到货运表中。

你可能会疑问,身份证等等逻辑我是拷贝的,怎么还需要测试。你怎么保证你拷贝对了?很多问题都是一些小bug引起的,你既然写了这么多代码 那你就要去测试。如果抽取出公有逻辑,我只需要测试查询货运人员的代码和同步货运人员的代码, 因为你只写了这些逻辑。 公有的代码你又没有修改不需要测试。

希望你们能理解慢慢的业务扩充,因为有其他业务才会有相同的逻辑需要抽取出来,让子类去继承这个类去实现子类代码的个性化开发。而不是一开始就写一个父类。这样除了让你工程出现大量继承外没有任何意义,类越来越多,后期难以维护。

看一下接口:

看一下LocalCache的代码逻辑:

使用线程安全的ConcurrentHashMap保存数据,add()方法将数据加入到缓存中,get()方法从缓存中获取数据、现在的LocalCache的get()方法 如果缓存没有数据就返回空。

问题:有一些业务场景,缓存数据没有的时候,需要将这部分查询出来,能查询到需要将数据添加到缓存中。

比如UseLocalCache这个类,使用缓存保存学生信息。getStudentId()方法先从缓存LocalCache获取学生信息,如果缓存没有学生信息,则从数据库读取学生信息,查询出学生信息后,加入到缓存LocalCache中,并返回。

根据这个业务特点,缓存LocalCache能不能抽象的更深一些,功能更多一些。

将LocalCache的代码变成如下形式:

问题:

这个getData()方法LocalCache怎么实现呢?LocalCache不知道去哪里查询数据,但是用户知道,那让用户告诉你去哪里查询。代码改成如下形式

定义Load接口的load()方法,用户使用LocalCache的时候,可以实现这个接口,告诉LocalCache去哪里查询数据。

LocalCache的get()方法逻辑变更为,当数据在内存中时,直接返回内存的数据。如果数据不在内存中,可以使用Load接口的load()方法加载数据,加载到数据后,放到内存,然后返回。

缓存使用者UserLocalCache代码简化了很多,只需要实现LocalCache的laod()方法即可。

接口定义了一种行为规范。 已上面代码为例,写LocalCache代码的工程师,当数据不在内存的时候,需要读取数据,然后更新到内存中。但是他又不知道去哪里获取这个数据,但是使用LocalCache的人知道,那么给使用者提供一个接口Load,让使用者去实现这个接口的load()方法。 这样LocalCache的get()方法逻辑就可以抽取出来。

这也是中间件或者很多工具类使用过程需要实现一些接口的原因。 中间件开发工程师将主要流程抽取了出来,但是一些关键数据或者一些关键状态流转,需要用户告诉这些中间件,那么中间件会给用户提供接口,用户实现这个接口就可以使用中间件去完成自己的业务逻辑。无论接口,xml文件或yml文件,都是这个道理。

#大厂##技术##面试题目#
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务