面试题答案
一键面试接口设计原则
- 单一职责原则:每个接口只负责一项明确的功能。这样当业务变化时,只影响到相关的特定接口,不会波及整个接口体系。例如,在电商系统中,将用户登录验证和用户信息查询分别设计为两个接口
UserLoginService
和UserInfoQueryService
,而不是将所有用户相关操作放在一个接口中。 - 依赖倒置原则:高层模块不应该依赖底层模块,二者都应该依赖抽象(接口)。通过面向接口编程,降低模块间的耦合度。例如,在订单处理模块中,订单业务逻辑层不直接依赖具体的数据库持久化实现类,而是依赖
OrderDao
接口,这样当数据库持久化方式从 MySQL 切换到 MongoDB 时,只需要实现新的OrderDao
接口实现类,而订单业务逻辑层代码无需修改。 - 里氏替换原则:所有引用基类(接口)的地方必须能透明地使用其子类的对象。这确保了系统的稳定性,当用子类替换接口实现时,不会破坏原有系统的功能。例如,在图形绘制系统中,定义
Shape
接口,有draw
方法,Circle
和Rectangle
类实现Shape
接口,在绘图工具中,使用Shape
接口来接收各种形状对象进行绘制,无论传入Circle
还是Rectangle
对象都能正确绘制。 - 接口隔离原则:客户端不应该依赖它不需要的接口。将大的接口拆分成多个小的接口,让不同的客户端只依赖它们需要的接口。比如在一个综合管理系统中,对于员工管理模块,不同角色(管理员、普通员工)有不同操作权限,将员工管理接口按权限拆分为
AdminEmployeeManagement
接口(包含添加、删除员工等操作)和EmployeeSelfManagement
接口(包含查看个人信息、修改密码等操作),不同角色的客户端只依赖对应的接口。
业务场景及设计示例
以在线教育平台为例:
- 课程管理场景:
- 接口设计:定义
CourseService
接口,包含课程创建、课程查询、课程修改、课程删除等方法。
public interface CourseService { void createCourse(Course course); Course getCourseById(int courseId); void updateCourse(Course course); void deleteCourse(int courseId); }
- 实现类:有
DatabaseCourseServiceImpl
类实现该接口,通过数据库操作实现课程管理功能。
public class DatabaseCourseServiceImpl implements CourseService { // 数据库连接及相关操作代码 @Override public void createCourse(Course course) { // 执行数据库插入课程操作 } @Override public Course getCourseById(int courseId) { // 执行数据库查询课程操作 return null; } @Override public void updateCourse(Course course) { // 执行数据库更新课程操作 } @Override public void deleteCourse(int courseId) { // 执行数据库删除课程操作 } }
- 优点:如果未来业务变化,比如需要添加课程发布、课程下架等功能,可以在
CourseService
接口中新增方法,而不影响其他依赖CourseService
现有方法的模块。如果需要更换课程数据存储方式,从关系型数据库切换到非关系型数据库,只需要创建新的实现类实现CourseService
接口,如NoSqlCourseServiceImpl
,而业务逻辑层中依赖CourseService
的代码无需改变,降低了耦合度,提高了可维护性和扩展性。
- 接口设计:定义
- 学生选课场景:
- 接口设计:定义
EnrollmentService
接口,负责处理学生选课、退课等操作。
public interface EnrollmentService { void enrollStudent(int studentId, int courseId); void dropCourse(int studentId, int courseId); }
- 实现类:
DefaultEnrollmentServiceImpl
类实现该接口,与课程管理接口(CourseService
)通过接口依赖进行交互,如在选课操作时先查询课程是否存在等。
public class DefaultEnrollmentServiceImpl implements EnrollmentService { private CourseService courseService; public DefaultEnrollmentServiceImpl(CourseService courseService) { this.courseService = courseService; } @Override public void enrollStudent(int studentId, int courseId) { Course course = courseService.getCourseById(courseId); if (course!= null) { // 执行选课逻辑,如更新数据库选课关系表 } } @Override public void dropCourse(int studentId, int courseId) { // 执行退课逻辑 } }
- 优点:通过接口依赖,
EnrollmentService
不依赖CourseService
的具体实现,只依赖其接口。如果CourseService
实现发生变化,只要接口不变,EnrollmentService
的实现不需要改变,保证了系统的高可维护性和扩展性。同时,如果未来业务增加学生选课限制(如选课人数限制等),可以在EnrollmentService
接口中新增方法或者修改现有方法,而不会影响其他不相关模块。
- 接口设计:定义