что лучший способ состоит в том, чтобы смоделировать many-many отношения?
позволяет говорят, что у нас есть два классы, Команда и Игрок
Мне нравится называть методы как
playerX.getTeamList()
для получения списка всей Команды s, он находится вteamY.getPlayerList()
получить список всего Плеера s в команде(или имейте некоторый другой способ сделать это эффективно),
Я могу думать о двух способах сделать это, но они просто не делают чувствует себя подобно хорошим башмакам ООП. можно ли думать о каких-либо хороших путях, возможно, башмак дизайна?
Отношения между игроками и командами образуют двудольный граф. Жду комментариев (и даунвотов?)! Я OOD нооб.
class MyPlayer
{
public string Name { get; set; }
public MyPlayer(string n)
{
Name = n;
}
}
class MyTeam
{
public string Name { get; set; }
public MyTeam(string n)
{
Name = n;
}
}
class PlayerTeamPair
{
public MyPlayer Player { get; set; }
public MyTeam Team { get; set; }
public PlayerTeamPair(MyPlayer p,MyTeam t)
{
Player = p;
Team = t;
}
}
class PlayerTeamBipartiteGraph
{
public List<PlayerTeamPair> Edges { get; set; }
public PlayerTeamBipartiteGraph()
{
Edges = new List<PlayerTeamPair>();
}
public void AddPlayerAndTeam(MyPlayer p, MyTeam t)
{
Edges.Add(new PlayerTeamPair(p, t));
}
public List<MyTeam> GetTeamList(MyPlayer p)
{
var teams = from e in Edges where e.Player == p select e.Team;
return teams.ToList<MyTeam>();
}
public List<MyPlayer> GetPlayerList(MyTeam t)
{
var players = from e in Edges where e.Team == t select e.Player;
return players.ToList<MyPlayer>();
}
}
class Program
{
static void Main(string[] args)
{
var G = new PlayerTeamBipartiteGraph();
MyPlayer a = new MyPlayer("A");
MyPlayer b = new MyPlayer("B");
MyPlayer c = new MyPlayer("C");
MyPlayer d = new MyPlayer("D");
MyTeam t1 = new MyTeam("T1");
MyTeam t2 = new MyTeam("T2");
G.AddPlayerAndTeam(a, t1);
G.AddPlayerAndTeam(b, t1);
G.AddPlayerAndTeam(c, t1);
G.AddPlayerAndTeam(b, t2);
G.AddPlayerAndTeam(d, t2);
G.GetTeamList(b).ForEach(t => Console.Write(" {0} ",t.Name));
Console.WriteLine();
G.GetPlayerList(t2).ForEach(p => Console.Write(" {0} ",p.Name));
Console.WriteLine();
}
}
public class Player
{
public Team[] Teams {get;set;}
}
public class Team
{
public Player[] Players {get;set;}
}
Совершенно разумно.
IMHO то, что вы описываете - это "естественный" путь для OO. Ваш XXX.getXXXList() - это интерфейс к вашим классам. И для ограниченного числа классов это будет правильный путь.
Представьте, что есть 1000 классов, которые могут быть "взаимосвязаны". Тогда может быть интересно иметь некий ManyToManyManager, который может закинуть объект, добавить другой объект к связанным объектам объекта и получить список всех объектов, связанных с другим. Это было бы своего рода делегирование против реализации.
Шуре, если вы делегируете ваше отношение "многие-ко-многим" другому экземпляру, ваша объектная модель больше не отражает это отношение "многие-ко-многим".
Разделите отношение «многие ко многим» на два отношения «один ко многим». Все становится намного проще.
все в порядке, Player
имеет коллекцию Team
и Team
имеет коллекцию Player
. Вам нужно быть осторожным с целостностью в операциях добавления/удаления, потому что они не являются "атомарными"
Стоит отличать ощущение API от реальной реализации.
Хотя для обоих классов имеет смысл предоставлять такую коллекцию (например, get * List ()), они не обязательно должны содержать экземпляр коллекции.
Я предлагаю вам создать класс League
или что-то в этом роде, которое будет содержать своего рода частный словарь сопоставлений игроков и команд. Добавления к этим «коллекциям» в экземпляре Team / Player должны вызывать внутренние методы в экземпляре League
для обновления сопоставлений. Таким образом, вы сохраняете атомарные обновления (как предложил Андрей) и безошибочные.
Ответ от Уилла правильный. Однако, чтобы разобраться с синхронизацией, я бы, вероятно, начал с ObservableCollection. Пусть одна сторона отношения будет "ведущей", которая отслеживает добавления/удаления на другой стороне и занимается синхронизацией.
Однако имейте в виду, что если один объект подписывается на события другого, то это сильная ссылка, которая предотвратит сборку мусора. Скорее всего, они будут покидать область видимости одновременно, так что это не проблема, но об этом следует помнить.