面向对象编程中数据库与对象交互设计及类方法实现咨询
面向对象设计中数据库与对象的协作及第三方服务调用实践
一、Student类方法直接操作数据库的合理性分析
直接在enrollForACourse()、getAllStudentCourses()这类方法中操作数据库,不符合面向对象设计的最佳实践,核心问题是破坏了单一职责原则,导致类的内聚性下降:
- Student类的核心职责应该是封装学生的业务逻辑(比如选课规则校验、GPA计算),而非处理数据持久化。把数据库操作塞进Student类,会让它同时承担领域对象和数据访问的双重角色,代码耦合度飙升——比如换数据库类型时,你得修改Student类的代码,而非只改数据访问层。
- 内聚性层面:
enrollForACourse()本该专注于"判断学生是否符合选课条件"这类业务逻辑,现在还要写JDBC或ORM调用代码,方法职责混杂,后续维护和测试都会变得困难(单元测试还要依赖真实数据库)。
优化方向:Repository模式分离数据访问
正确的做法是引入Repository层,专门负责数据的CRUD操作,Student类只专注业务逻辑:
getAllStudentCourses():Student类只需持有内存中的courses集合,直接返回该集合的副本即可;如果需要从数据库加载课程数据,由StudentRepository的findCoursesByStudentNumber()方法完成,再将数据注入到Student对象中。enrollForACourse():Student类负责校验选课规则(比如已选课程数是否超限、是否满足先修课要求),实际的数据库更新操作交给StudentRepository的save()方法执行。
二、Student类调用第三方服务的处理方案
同样遵循关注点分离原则,绝对不能让Student类直接调用第三方服务,否则会导致领域对象与外部服务强耦合,后续替换服务或测试都会非常麻烦。推荐两种实现方式:
1. 引入服务层封装外部调用
创建专门的服务类(比如CourseEnrollmentService),把第三方服务的调用逻辑封装在其中,Student类通过依赖注入的方式使用这个服务:
- Student类只负责业务规则校验,调用服务类的方法完成实际的外部交互和数据持久化。
- 服务层可以同时处理第三方服务调用和数据库操作,让领域对象彻底摆脱外部依赖。
2. 适配器模式适配外部接口
如果第三方服务的接口与系统内部规范不一致,可以用适配器模式将其转换为内部统一接口。这样Student类依赖的是内部接口,而非具体的第三方服务实现,后续替换服务时只需更换适配器即可,无需修改Student类代码。
代码示例
优化后的Student类(专注业务逻辑)
public class Student { private String name; private String number; private List<Course> courses; public Student(String name, String number) { this.name = name; this.number = number; this.courses = new ArrayList<>(); } // 业务逻辑:校验选课规则并调用服务完成选课 public boolean enrollForACourse(Course course, CourseEnrollmentService enrollmentService) { if (courses.size() >= 5) { System.out.println("已选课程数超限,无法选课"); return false; } boolean enrollSuccess = enrollmentService.enroll(this, course); if (enrollSuccess) { courses.add(course); } return enrollSuccess; } // 返回内存中的课程列表,无需直接查数据库 public List<Course> getAllStudentCourses() { return new ArrayList<>(courses); } // 基于自身课程数据计算GPA public double getStudentGPA() { if (courses.isEmpty()) { return 0.0; } double totalScore = 0; int totalCredit = 0; for (Course course : courses) { totalScore += course.getScore() * course.getCredit(); totalCredit += course.getCredit(); } return Math.round(totalScore / totalCredit * 100.0) / 100.0; } // getter方法 public String getNumber() { return number; } }
CourseEnrollmentService(封装第三方服务与数据库操作)
public class CourseEnrollmentService { private final StudentRepository studentRepo; private final ThirdPartyCourseService thirdPartyService; public CourseEnrollmentService(StudentRepository studentRepo, ThirdPartyCourseService thirdPartyService) { this.studentRepo = studentRepo; this.thirdPartyService = thirdPartyService; } public boolean enroll(Student student, Course course) { // 调用第三方服务完成选课校验 boolean thirdPartyOk = thirdPartyService.verifyEnrollment(student.getNumber(), course.getId()); if (!thirdPartyOk) { return false; } // 更新数据库 studentRepo.save(student); return true; } }
StudentRepository(数据访问层)
public interface StudentRepository { void save(Student student); Student findByNumber(String studentNumber); List<Course> findCoursesByStudentNumber(String studentNumber); }
总结
- 内聚性优化:让Student类只做"学生该做的事",数据持久化和外部服务调用交给专门的层,类的职责清晰,内聚性更高。
- 数据库操作:用Repository模式彻底分离数据访问逻辑,降低耦合,提升代码可维护性。
- 第三方服务:通过服务层或适配器解耦领域对象与外部依赖,方便测试和后续扩展。
内容的提问来源于stack exchange,提问作者Alexeia
相关产品推荐
相关产品推荐

