Java: Объектно-ориентированный дизайн

Теория: Связь многие ко многим

Помимо связи один-ко-многим, очень распространена связь многие-ко-многим. Например, такой связью обладают курсы и пользователи. С одной стороны, пользователь может проходить множество курсов, с другой, курс проходится большим количеством студентов.

Кажется, что такую связь можно реализовать, сделав зависимую сущность коллекцией с обоих концов, со стороны курса и со стороны пользователя.

user.addCourse(course);
user.getCourses();
// или
course.addUser(user);
course.getUsers();

На практике же, такая реализация не позволяет смоделировать нашу предметную область правильно. Когда человек вступает в курс, то у него появляется дата вступления в курс, кроме этого, курс можно закончить, а это обязательно должно быть где-то отражено. Эта информация не относится ни к курсу, ни к пользователю, она относится к их связи.

Такую связь реализуют с помощью введения третьей сущности, которая может и, обычно, содержит какие-то дополнительные данные появляющиеся только во время создания связи. В случае курсов, мы точно хотим знать когда пользователь начал курс и когда он его закончил. Помимо этого мы можем добавить другую информацию, которая привязана именно к связи, а не к пользователю или курсу.

В случае курсов и пользователей, сущность, которая связывает курсы и пользователи можно назвать CourseMember (участник курса). Вот ее код:

import java.time.LocalDate;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class CourseMember {
    private Course course;
    private User user;

    private LocalDate startedAt;
    private LocalDate finishedAt;
}

И использование:

var course = new Course("Java ООП");
var user = new User("Mila");

var member = new CourseMember();
member.setCourse(course);
member.setUser(user);
member.setStartedAt(LocalDate.now());

Мы связали курсы и пользователей связью многие-ко-многим, при этом получившаяся сущность CourseMember связана с курсом связью один-ко-многим и с пользователем связью один-ко-многим. Визуально это выглядит так.

+----------------+          +---------------------+          +----------------+
|      User      |          |    CourseMember     |          |     Course     |
+----------------+          +---------------------+          +----------------+
| - attributes   |1        *| - Course            |*        1| - attributes   |
| - methods      |<---------| - User              |--------->| - methods      |
+----------------+          | - startedAt         |          +----------------+
                            | - finishedAt        |
                            +---------------------+

Для полной реализации таких связей, нам нужно добавить CourseMember в каждую из зависимых сущностей.

@Setter
@Getter
class User {
    private String name;
    private List<CourseMember> courseMembers;

    public User(String name) {
        this.name = name;
        courseMembers = new ArrayList<>();
    }

    public void addCourseMember(CourseMember courseMember) {
        courseMembers.add(courseMember);
    }

    public void removeCourseMember(CourseMember courseMember) {
        courseMembers.remove(courseMember);
    }

    // другие методы
}

@Setter
@Getter
class Course {
    private String name;
    private List<CourseMember> courseMembers;

    public Course(String name) {
        this.name = name;
        courseMembers = new ArrayList<>();
    }

    public void addCourseMember(CourseMember courseMember) {
        courseMembers.add(courseMember);
    }

    public void removeCourseMember(CourseMember courseMember) {
        courseMembers.remove(courseMember);
    }

    // другие методы
}

@Getter
class CourseMember {
    private User user;
    private Course course;
    @Setter
    private LocalDate startedAt;
    @Setter
    private LocalDate finishedAt;

    public void setCourse(Course course) {
        this.course = course;
        course.addCourseMember(this);
    }

    public void setUser(User user) {
        this.user = user;
        user.addCourseMember(this);
    }
}

Рекомендуемые программы

Дальше

Завершено

0 / 5

+7 800 100 22 47

бесплатно по РФ

+7 495 085 21 62

бесплатно по Москве

Республика Казахстан, г. Алматы,
ул. Ауэзова, д. 14А
БИН 230340043714