В ответ на @Jason D и ради @Nitax: я действительно сглаживаю поверхность, потому что, хотя она в основном проста, она также может усложниться. Я не собираюсь переписывать его лучше, чем Мартин Фаулер (конечно, не через 10 минут).
Прежде всего вам нужно разобраться с проблемой только одного объекта в памяти, относящегося к определенному депо. Мы достигнем этого с помощью чего-то, называемого репозиторием. CustomerRepository
имеет метод GetCustomer()
, а метод DepotRepository
имеет метод GetDepot()
. Я буду махать руками и притворяться, что это происходит.
Во-вторых, вам нужно будет написать несколько тестов, которые показывают, как вы хотите, чтобы код работал. Я не знаю этого, но все равно несу.
// sample code for how we access customers and depots
Customer customer = Repositories.CustomerRepository.GetCustomer("Bob");
Depot depot = Repositories.DepotRepository.GetDepot("Texas SW 17");
Теперь твердая часть здесь: Как вы хотите моделировать отношения? В системах OO вам действительно не нужно ничего делать. В C# I может просто сделать следующее.
Клиенты сохранить список депо они с
class Customer
{
public IList<Depot> Depots { get { return _depotList; } }
}
альтернативно, Депо хранить список клиентов, они с
class Depot
{
public IList<Customer> Customers { get { return _customerList; } }
}
// * code is very brief to illustrate.
В это самая основная форма, любое количество клиентов может ссылаться на любое количество депо. m: n решена. Ссылки дешевы в OO.
Помните, что проблема, с которой мы столкнулись, заключается в том, что, хотя Клиент может хранить список ссылок на все хранилища, о которых он заботится (первый пример), Депо не может перечислить всех Клиентов.
Чтобы получить список всех клиентов для Depot (первый пример), мы должны написать код, который перебирает всех клиентов и проверяет свойство customer.Depots:
List<Customer> CustomersForDepot(Depot depot)
{
List<Customer> allCustomers = Repositories.CustomerRepository.AllCustomers();
List<Customer> customersForDepot = new List<Customer>();
foreach(Customer customer in allCustomers)
{
if(customer.Depots.Contains(depot))
{
customersForDepot.Add(customer);
}
}
return customersForDepot;
}
Если бы мы использовали Linq, мы мог бы написать его как
var depotQuery = from o in allCustomers
where o.Depots.Contains(depot)
select o;
return query.ToList();
У вас 10 000 000 клиентов, которые хранятся в базе данных? Ой! Вы действительно не хотите загружать всех 10 000 000 клиентов каждый раз, когда Депо должно определять своих «клиентов». С другой стороны, если у вас есть только 10 хранилищ, запрос, загружающий все хранилища один раз и некоторое время, не имеет большого значения. Вы всегда должны думать о своих данных и о своей стратегии доступа к данным.
Мы могли иметь список в обоих Customer
и Depot
. Когда мы это делаем, мы должны быть осторожны в реализации. При добавлении или удалении ассоциации мы должны внести изменения в оба списка одновременно. В противном случае у нас есть клиенты, думающие, что они связаны с депо, но депо ничего не знает о клиенте.
Если нам это не нравится, и мы решили, что нам действительно не нужно связывать объекты так плотно. Мы можем удалить явный список и ввести третий объект, который является только отношением (а также включать другой репозиторий).
class CustomerDepotAssociation
{
public Customer { get; }
public Depot { get; }
}
class CustomerDepotAssociationRepository
{
IList<Customer> GetCustomersFor(Depot depot) ...
IList<Depot> GetDepotsFor(Customer customer) ...
void Associate(Depot depot, Customer customer) ...
void DeAssociate(Depot depot, Customer customer) ...
}
Это еще одна альтернатива. Репозитарию ассоциации не нужно раскрывать, как он связывает клиентов с хранилищами (и, кстати, из того, что я могу сказать, это то, что пытается сделать код @Jason D)
Я могу предпочесть отдельный объект в этом случае, потому что то, что мы говорим, является ассоциацией Клиента и Депо, является сущностью для себя.
Так идти вперед и читать некоторые Domain Driven Design книги, а также купить Martin Fowlers PoEAA (Узоры Enterprise Application Architecture)
Просто некоторые идеи: 1. TreeView парадигма: каждый Клиент является дочерним узлом Узлы клиентов узла депо. 2. Составной объект с взаимными ссылками: каждый объект депо - объект, который поддерживает список: у каждого клиента есть поле, поддерживающее ссылку на его депо. –
BillW
Я бы рекомендовал посмотреть на шаблоны архитектуры предприятия Мартином Фаулером. Это отличная книга и многое покрывает то, о чем вы просите. –