アプリケーション レベルで多対多の関係でいくつかの単純なリストを管理しようとしています。オブジェクト間で接続が確立されるたびに、両方のオブジェクトの関係を更新しようとしています (例: teacher.AddStudent()
) student.RemoveTeacher()
。
SQL を使用していた場合StudentTeacher
、関係を管理するためにテーブルのようなものを使用することになることは承知していますが、アプリケーション内でこれを行う方法を理解しようとしています。
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace StudentTeacher
{
// create simple interface
public interface IPerson {}
// abstract class
public abstract class Person : IPerson
{
public int Id { get; set; }
}
// concrete "Teacher"
public class Teacher : Person
{
// private list of student ids
private List<int> _studentIds { get; set; }
// readonly accessor
public ReadOnlyCollection<int> StudentIds {
get { return _studentIds.AsReadOnly(); }
}
// constructor
public Teacher(int id) {
Id = id;
_studentIds = new List<int>();
}
// add a student
public void AddStudent(Student student)
{
if (!_studentIds.Contains(student.Id)) {
_studentIds.Add(student.Id);
student.AddTeacher(this);
}
}
// remove a student
public void RemoveStudent(Student student)
{
if (_studentIds.Contains(student.Id)) {
_studentIds.Remove(student.Id);
student.RemoveTeacher(this);
}
}
public string ToString() {
return String.Format("Id:{0} | StudentIds:{1}", Id, String.Join(",", StudentIds));
}
}
/// concrete "Student"
public class Student : Person
{
// private list of teacher ids
private List<int> _teacherIds { get; set; }
// readonly accessor
public ReadOnlyCollection<int> TeacherIds {
get { return _teacherIds.AsReadOnly(); }
}
// constructor
public Student(int id) {
Id = id;
_teacherIds = new List<int>();
}
// add a teacher
public void AddTeacher(Teacher teacher)
{
if (!_teacherIds.Contains(teacher.Id)) {
_teacherIds.Add(teacher.Id);
teacher.AddStudent(this);
}
}
// remove teacher
public void RemoveTeacher(Teacher teacher)
{
if (_teacherIds.Contains(teacher.Id)) {
_teacherIds.Remove(teacher.Id);
teacher.RemoveStudent(this);
}
}
// simple override
public string ToString() {
return String.Format("Id:{0} | TeacherIds:{1}", Id, String.Join(",", TeacherIds));
}
}
class Program
{
static void Main(string[] args)
{
// create teachers
var teacher1 = new Teacher(101);
var teacher2 = new Teacher(102);
// create students
var student1 = new Student(501);
var student2 = new Student(502);
var student3 = new Student(503);
// create some relationships
teacher1.AddStudent(student1);
teacher1.AddStudent(student2);
teacher1.AddStudent(student3);
// see what's happening
Console.WriteLine(teacher1.ToString()); // "Id:101 | StudentIds:501,502,503"
Console.WriteLine(student1.ToString()); // "Id:501 | TeacherIds:101"
Console.WriteLine(student2.ToString()); // "Id:502 | TeacherIds:101"
Console.WriteLine(student3.ToString()); // "Id:503 | TeacherIds:101"
// update student1, student2
student1.AddTeacher(teacher2);
student2.AddTeacher(teacher2);
// -- Outputs
Console.WriteLine(student1.ToString()); // "Id:501 | TeacherIds:101,102"
Console.WriteLine(student2.ToString()); // "Id:502 | TeacherIds:101,102"
Console.ReadLine();
}
}
}
私には、反対方向の add/remove メソッドを直接呼び出すのは適切ではありません。
if (!_studentIds.Contains(student.Id)) {
_studentIds.Add(student.Id);
student.AddTeacher(this); // calling this directly feels bad
}
これはすぐにめちゃくちゃになってしまう気がします。私の質問は次のとおりです。
- などの静的オブザーバーのようなものを追加
して、
StudentTeacherObserver
代わりにイベントを発生させる必要が ありますか?OnTeacherAdded
OnStudentAdded
- そのような関係を管理するための特定のパターンはありますか?
- この目的に適したより良いデータ構造はありますか?