搜索

12.2. 对域对象建模

download PDF

红帽构建的 OptaPlanner 时间表项目的目标是将每节分配给一个时间段和一个房间。为此,请添加三个类: TimeslotLessonRoom,如下图所示:

timeTableClassDiagramPure

Timeslot

Timeslot 类表示在未教授课程的时间间隔,例如: Monday 10:30 - 11:30Tuesday 13:30 - 14:30 - 14:30。在这个示例中,所有时间插槽都有相同的持续时间,且在 lunch 或其他中断期间没有时间插槽。

时间段没有日期,因为高校的计划只每周重复。无法进行持续 规划。次性被称为 问题事实,因为在解决过程中不会有定时实例变化。此类类不需要任何特定于 OptaPlanner 的注解。

room

Room 类代表了课程讲授的方式,例如 Room ARoom B。在本例中,所有空间都没有容量限制,它们可容纳所有课时。

房间 实例在解决过程中不会改变,因此 Room 也是 问题

lesson

在课时,由课课课表示,向班级教授一个主题,例如: A.Turing for a 9th gradeChemistry by M.Curie 为 10th grade如果一个主题每周都会为同一学员组讲授多次,则有多个小的、只能由 id 区分的实例。例如,第 9 分之时,每周有 6 个数学。

在寻求过程中,OptaPlanner 改变了 lesson 类的 timelot 和 room 字段,从而将每个较小的时间分配给一个时间段和一个房间。 因为 OptaPlanner 更改了这些字段,所以 lesson 是一个 规划实体

timeTableClassDiagramAnnotated

上图中的大多数字段包含输入数据,但 orange 字段除外。在输入数据中 未分配的 时间和房间 字段(null),并在输出数据中分配(而不是 null)。OptaPlanner 在解决过程中更改这些字段。这些字段称为规划变量。为了 OptaPlanner 可以识别它们,timelot 和 room 字段都需要 @PlanningVariable 注解。它们包含类( Lesson )需要 @PlanningEntity 注释。

流程

  1. 创建 src/main/java/com/example/domain/Timeslot.java 类:

    package com.example.domain;
    
    import java.time.DayOfWeek;
    import java.time.LocalTime;
    
    public class Timeslot {
    
        private DayOfWeek dayOfWeek;
        private LocalTime startTime;
        private LocalTime endTime;
    
        private Timeslot() {
        }
    
        public Timeslot(DayOfWeek dayOfWeek, LocalTime startTime, LocalTime endTime) {
            this.dayOfWeek = dayOfWeek;
            this.startTime = startTime;
            this.endTime = endTime;
        }
    
        @Override
        public String toString() {
            return dayOfWeek + " " + startTime.toString();
        }
    
        // ********************************
        // Getters and setters
        // ********************************
    
        public DayOfWeek getDayOfWeek() {
            return dayOfWeek;
        }
    
        public LocalTime getStartTime() {
            return startTime;
        }
    
        public LocalTime getEndTime() {
            return endTime;
        }
    
    }

    请注意,toString() 方法保留了输出短片,以便可以更轻松地读取 OptaPlanner 的 DEBUG 或 abrt 日志,如稍后所示。

  2. 创建 src/main/java/com/example/domain/Room.java 类:

    package com.example.domain;
    
    public class Room {
    
        private String name;
    
        private Room() {
        }
    
        public Room(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return name;
        }
    
        // ********************************
        // Getters and setters
        // ********************************
    
        public String getName() {
            return name;
        }
    
    }
  3. 创建 src/main/java/com/example/domain/Lesson.java 类:

    package com.example.domain;
    
    import org.optaplanner.core.api.domain.entity.PlanningEntity;
    import org.optaplanner.core.api.domain.variable.PlanningVariable;
    
    @PlanningEntity
    public class Lesson {
    
        private Long id;
    
        private String subject;
        private String teacher;
        private String studentGroup;
    
        @PlanningVariable(valueRangeProviderRefs = "timeslotRange")
        private Timeslot timeslot;
    
        @PlanningVariable(valueRangeProviderRefs = "roomRange")
        private Room room;
    
        private Lesson() {
        }
    
        public Lesson(Long id, String subject, String teacher, String studentGroup) {
            this.id = id;
            this.subject = subject;
            this.teacher = teacher;
            this.studentGroup = studentGroup;
        }
    
        @Override
        public String toString() {
            return subject + "(" + id + ")";
        }
    
        // ********************************
        // Getters and setters
        // ********************************
    
        public Long getId() {
            return id;
        }
    
        public String getSubject() {
            return subject;
        }
    
        public String getTeacher() {
            return teacher;
        }
    
        public String getStudentGroup() {
            return studentGroup;
        }
    
        public Timeslot getTimeslot() {
            return timeslot;
        }
    
        public void setTimeslot(Timeslot timeslot) {
            this.timeslot = timeslot;
        }
    
        public Room getRoom() {
            return room;
        }
    
        public void setRoom(Room room) {
            this.room = room;
        }
    
    }

    Lesson 类具有 @PlanningEntity 注释,因此 OptaPlanner 知道这个类在解决过程中发生了变化,因为它包含一个或多个计划变量。

    time lot 字段具有 @PlanningVariable 注释,因此 OptaPlanner 知道它可以更改其值。为了查找要分配给此字段的潜在的 Timeslot 实例,OptaPlanner 使用 valueRangeProviderRefs 属性连接到一个提供 List<Timeslot> 的值供应商。有关值范围供应商的信息,请参阅 第 12.4 节 “在规划解决方案中收集域对象”

    出于同样原因,room 字段还具有 @PlanningVariable 注释。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.