2

我想创建简单的学校应用程序,提供成绩、笔记、状态等。给学生、老师和家长。我正在尝试为这个问题设计对象,但我有点困惑——因为我在类设计方面不是很有经验。我现在的一些对象是:

class PersonalData() {
    private String name;
    private String surename;
    private Calendar dateOfBirth;
    [...]
}

class Person {
    private PersonalData personalData;
}

class User extends Person {
    private String login;
    private char[] password;
}

class Student extends Person {
    private ArrayList<Counselor> counselors = new ArrayList<>();
}

class Counselor extends Person {
    private ArrayList<Student> children = new ArrayList<>();
}

class Teacher extends Person {
    private ArrayList<ChoolClass> schoolClasses = new ArrayList<>();
    private ArrayList<Subject> subjects = new ArrayList<>();
}

这当然是一个普遍的想法。但我确信这不是最好的方法。例如,我希望一个人既可以是老师,也可以是父母(辅导员),而目前的方法使我拥有两个 Person 对象。我希望该用户在成功登录后获得它拥有的所有角色(学生或教师或(教师和家长))。我认为我应该制作和使用一些接口,但我不确定如何正确地做到这一点。也许是这样的:

interface Role {
}

interface TeacherRole implements Role {
    void addGrade( Student student, Grade grade, [...] );
}

class Teacher implements TeacherRole {
    private Person person;
    [...]
}

class User extends Person{
    ArrayList<Role> roles = new ArrayList<>();
}

请如果有人可以帮助我做到这一点,或者只是将我指向一些涵盖实用对象设计的文献/文章。

4

2 回答 2

2

在这样的系统中,您似乎可以创建一个包含所有个人属性以及帐户信息的 User 类:

public class User
{
   // personal properties
   private String name;
   private String surname;
   private Calendar dateOfBirth;

   // account properties;
   private String login;
   private String password; // note that string may be more convenient than char[]

   // role properties
   public ArrayList<Role> roles;
   ...

   public bool hasRole(Role role) // or isInRole(Role role)
   { // implementation here. }
}

然后你有你的角色对象:

public class Role
{
    private String name;
    private String description;
}

请注意,只有一个角色类可以是教师、学生、家长等。由于角色类是通用的,因此我们在其中没有诸如 addGrade() 之类的函数,因为这是特定于教师的。

当用户使用正确的凭据登录时,这样的系统将已经知道与用户关联的角色。通常,特定于角色的选项卡、链接和其他 UI 元素会根据角色显示(或不显示)。您可以在此处检查登录的用户是否具有特定角色(user.hasRole(...))。对于每个可见性由角色确定的 UI 元素,您必须有一个 if (user.hasRole(...))。

在组合问题上,这个系统是一个严重依赖对象之间关系的系统。让我们考虑一下学生和辅导员之间的关系——辅导员有学生分配给他/她。同样,任何给定的学生都有许多辅导员。你有一个多对多的关系,它需要一个结构来跟踪独特的学生辅导员对的组合:

public class StudentCounselor
{
     public User student;
     public User counselor;
}

谁来跟踪这一切?很可能是系统本身,而不是其他用户。

public class SystemAdministration
{
     public static ArrayList<StudentCounselor> studentCounselors = new ArrayList<StudentCounselor>();

     public static void addStudentCounselor(User student, User counselor)
     {
         //  Check to see first that the student-counselor combo doesn't exist

         studentCounselors.addItem(student, counselor);
         // addItem may not be the precise name of the function in ArrayList.
     }

     // function to obtain all students of a counselor
     public static ArrayList<User> getStudentsOfCounselor(User counselor)
     {
         // iterate through the studentCounselors ArrayList and pick only
         // the Student-Counselor whose counselor is the same counselor
         // as the one passed into this function.
         // Then extract the student property out of the fitting 
         // Student-Counselor.
         // Return the list of students. 
     }

     public static ArrayList<User> getCounselorsOfStudent(User student)
     {
         // Similar as above, but the other way around.
     }

}

你会为你的其他关系做类似的事情——家长-学生、教师-部分等。 SystemAdministration 类不是一个角色,而是负责为你提供所有数据的实体。

作为建议,请考虑 Section 对象:

public class Section
{
    public User teacher; // who teaches it
    public Course course; // what is the subject, because > 1 teacher might teach the same one.
    public TimeBlock timeBlock; // when is this section administered?
    public Venue venue; // what room or what facility
}

您必须创建 TimeBlock 和 Venue 类。这种结构,当放入 ArrayList 时将能够回答以下问题:“作为教师,我将教哪些部分?” 这就回答了“我将教他们什么科目、什么时候、在哪里教他们?”这个问题。

至于学生,你需要 StudentSection “组合”类:

public class StudentSection
{
    public Section section;
    public User student;
}

当放入 SystemAdministrator 类的 ArrayList 时,现在您可以遍历列表以提取分配给学生的部分(也就是学生的日程安排),同样,谁是给定部分的学生。

请注意,除了角色之外,我们在 User 类中没有相关项目的列表。要获取任何数据,只要您在全局(在本例中为 SystemAdministration)结构中拥有所有数据和访问功能,有关登录用户及其角色的信息就足够了。

于 2012-12-05T15:28:12.840 回答
1

没有“正确”的设计;这一切都取决于您计划如何与这些类/接口进行交互。尝试以最自然的方式勾勒出您打算调用的方法,并从中工作以了解您的类的良好布局可能是什么。如果您觉得勇敢,请尝试学习测试驱动开发方法;在“真实”代码之前编写实际的单元测试可以帮助您了解类结构。

作为一般建议,尽量避免继承,而倾向于组合。拥有一个元素数组Role是朝着这个方向迈出的一步。尝试了解您计划与这些角色进行交互,并相应地添加方法。

于 2012-12-05T13:10:22.840 回答