Если вы используете Spring Framework:
public static void main(String[] args) {
String uri = "http://youhost.com/test?param1=abc¶m2=def¶m2=ghi";
MultiValueMap<String, String> parameters =
UriComponentsBuilder.fromUriString(uri).build().getQueryParams();
List<String> param1 = parameters.get("param1");
List<String> param2 = parameters.get("param2");
System.out.println("param1: " + param1.get(0));
System.out.println("param2: " + param2.get(0) + "," + param2.get(1));
}
Вы получите:
param1: abc
param2: def,ghi
Благодаря всем, кто ответил, некоторые действительно интересные подходы! В конце я должен был сделать что-то в большой спешке, таким образом, это - то, что я придумал:
Представленный третий объект, названный WellKnownContact
и соответствующий WellKnownContactType
перечисление:
public class Company
{
public string Name { get; set; }
public IList<Employee> Employees { get; private set; }
private IList<WellKnownEmployee> WellKnownEmployees { get; private set; }
public Employee ContactPerson
{
get
{
return WellKnownEmployees.SingleOrDefault(x => x.Type == WellKnownEmployeeType.ContactPerson);
}
set
{
if (ContactPerson != null)
{
// Remove existing WellKnownContact of type ContactPerson
}
// Add new WellKnownContact of type ContactPerson
}
}
}
public class Employee
{
public Company EmployedBy { get; set; }
public string FullName { get; set; }
}
public class WellKnownEmployee
{
public Company Company { get; set; }
public Employee Employee { get; set; }
public WellKnownEmployeeType Type { get; set; }
}
public enum WellKnownEmployeeType
{
Uninitialised,
ContactPerson
}
Это чувствует себя немного громоздким, но обходит проблему циклической ссылки и отображается чисто на DB, который сохраняет попытку заставить LINQ к SQL делать что-либо слишком умное! Также допускает несколько типов 'известных контактов', который определенно прибывает в следующий спринт (так не действительно YAGNI!).
Интересно, как только я придумал изобретенный пример Компании/Сотрудника, он сделал НАМНОГО легче думать о, в отличие от довольно абстрактных объектов, с которыми мы действительно имеем дело.
Ваше решение кажется довольно разумным.
Другая вещь думать о состоит в том, что Ваши объекты в памяти не должны точно соответствовать схеме базы данных. В базе данных у Вас может быть более простая схема с дочерними свойствами, но в памяти можно оптимизировать вещи и иметь родителя со ссылками на дочерние объекты.
Прием к решению этого должен понять, что родитель не должен знать обо всех методах ребенка, и что ребенок не должен знать все методы родителя. Поэтому можно использовать Интерфейсный Принцип Сегрегации для разъединения их.
Короче говоря, Вы создаете интерфейс для родителя, который имеет только те методы, в которых нуждается ребенок. Вы также создаете интерфейс для ребенка, который имеет только те методы, в которых нуждается родитель. Тогда у Вас есть родитель, содержат список дочерних интерфейсов, и у Вас есть дочерняя точка назад к родительскому интерфейсу. Я называю это Зеркально отраженный Шаблон Flob , потому что диаграмма UML имеет геометрию Eckles-иорданского триггера (Предъявите иск мне, я - старый инженер аппаратного обеспечения!)
|ISystemMenu|<-+ +->|IMenuItem|
A 1 \ / * A
| \/ |
| /\ |
| / \ |
| / \ |
| / \ |
|SystemMenu| |MenuItem|
Уведомление, что нет цикла в этой схеме. Вы не можете запустить в одном классе и следовать за стрелками назад к Вашей начальной точке.
Иногда, для получения разделения просто право, необходимо переместить некоторые методы. Мог бы быть код, что Вы думали, должен был быть в SystemMenu, который Вы перемещаете в MenuItem, и т.д. Но в целом техника работает хорошо.
Возможно, самосправочный шаблон Составного объекта GoF является порядком здесь. Меню имеет набор листа MenuItems, и у обоих есть единый интерфейс. Тем путем можно составить Меню из Меню и/или MenuItems. Схема имеет таблицу с внешним ключом, который указывает назад на его собственный первичный ключ. Работы с обходом меню тот путь, также.
Я действительно не вижу Вашей проблемы. Очевидно Вы используете C#, который содержит объекты как ссылки не экземпляры. Это означает, что прекрасно подходит, чтобы иметь перекрестные ссылки или даже самоссылку.
в C++ и других языках, где объекты являются большим количеством compositied тогда, у Вас могут быть проблемы, которые обычно решаются с помощью ссылок или указателей, но C# должен быть прекрасным.
[еще 114], чем, вероятно, Ваша проблема то, что Вы пытаетесь следовать за всеми ссылками так или иначе, ведя к циклической ссылке. LINQ использует ленивую загрузку для решения этой проблемы. Например, LINQ не загрузит Компанию или Сотрудника, пока Вы не сошлетесь на него. Просто необходимо избежать после таких ссылок далее, чем один уровень.
Однако Вы не можете действительно добавить две таблицы как каждый внешний ключ других, иначе Вы никогда не были бы в состоянии удалить любую запись, начиная с удаления сотрудника потребует удаления компании сначала, но Вы не можете удалить компанию, не удаляя сотрудника. Как правило, в этом случае Вы только использовали бы тот в качестве реального внешнего ключа, другой просто будет psuedo-FK (то есть, тот, который используется в качестве FK, но не включил ограничения). Необходимо решить, который является более важными отношениями.
В примере компании, Вы, вероятно, хотели бы удалить сотрудника, но не компанию, поэтому сделайте компанию-> сотрудник FK ограничительные отношения. Это препятствует тому, чтобы Вы удалили компанию, если существуют сотрудники, но можно удалить сотрудников, не удаляя компанию.
кроме того, постарайтесь не создавать новые объекты в конструкторе в этих ситуациях. Например, если Ваш объект Сотрудника создаст новый объект Компании, который включает нового сотрудника ojbect созданный для сотрудника, то он в конечном счете исчерпает память. Вместо этого передайте объекты, уже созданные конструктору, или установите их после конструкции, возможно при помощи initalization метода.
, Например:
Company c = GetCompany("ACME Widgets");
c.AddEmployee(new Employee("Bill"));
тогда, в AddEmployee, Вы устанавливаете компанию
public void AddEmployee(Employee e)
{
Employees.Add(e);
e.Company = this;
}
В коде у Вас должны быть ссылки оба способа сослаться на вещи оба пути. Но в базе данных, Вам только нужна ссылка один способ заставить вещи работать. Из-за дорожной работы соединений у Вас только должен быть внешний ключ в одной из Ваших таблиц. Когда Вы думаете об этом, каждый внешний ключ в Вашей базе данных мог быть зеркально отражен вокруг и создать и создавать циклическую ссылку. Лучше всего просто выбрать одну запись, в этом случае вероятно, ребенок с внешним ключом к родителю, и просто быть сделанными.
В домене управляемый смысл дизайна путь можно принять решение избежать двунаправленных отношений между объектами, где это возможно. Выберите один "совокупный корень", чтобы содержать отношения и использовать другой объект только когда навигация от совокупного корня. Я стараюсь избегать двунаправленных отношений, где это возможно. Из-за YAGNI, и это заставит Вас задать вопрос, "что было первым, курица или яйцо?" Иногда Вы будете все еще нуждаться в двунаправленных ассоциациях, затем выбирать одно из решений, упомянутых ранее.
/// This is the aggregate root
public class Company
{
public string Name { get; set; }
public IList<Employee> Employees { get; private set; }
public Employee ContactPerson { get; set; }
}
/// This isn't
public class Employee
{
public string FullName { get; set; }
}
Можно осуществить внешние ключи в базе данных, где две таблицы относятся друг к другу. Два пути приходят на ум:
я предположил здесь, что жизни объекта родительского меню в одной таблице и ребенок в другой таблице, но то же решение работало бы, если они находятся оба в той же таблице.
поддержка Многого DBMS задержала ограничительную проверку. Возможно Ваш делает также, хотя Вы не упоминаете, какой DBMS Вы используете