Двунаправленные ассоциации

До сих пор мы говорили об однонаправленных ассоциациях. К друго­му распространенному типу ассоциаций относится двунаправленная ассоциация, например, показанная на рис. 3.4.

Двунаправленная ассоциация - это пара свойств, связанных в противо­положных направлениях. Класс Саг (Автомобиль) имеет свойство


owner: Person[1], а класс Person (Личность) имеет свойство cars:Car[*]. (Обратите внимание, что я использовал множественную форму имени свойства cars, а это соглашение общепринятое, но ненормативное.)

Обратная связь между ними подразумевает, что если вы следуете обо­им свойствам, то должны вернуться обратно к множеству, содержаще­му вашу исходную точку. Например, если я начинаю с конкретной мо­дели MG Midget, нахожу ее владельца, а затем смотрю на множество принадлежащих ему машин, то оно должно включать модель Midget, с которой я начал.

В качестве альтернативы маркировки ассоциации по свойству многие люди, особенно если они имеют опыт моделирования данных, любят именовать ассоциации с помощью глаголов (рис. 3.5), чтобы отноше­ние можно было использовать в предложении. Это вполне допустимо, и можно добавить к ассоциации стрелку, чтобы избежать неопреде­ленности. Большинство разработчиков объектов предпочитают ис­пользовать имя свойства, так как оно больше соответствует функцио­нальным назначениям и операциям.

Некоторые разработчики тем или иным способом именуют каждую ас­социацию. Я предпочитаю давать имя ассоциации, только если это улучшает понимание. Слишком часто встречаются такие имена, как «has» (имеет) или «is related to» (связан с).

На рис. 3.4 двунаправленная природа ассоциации подчеркивается стрелками на обоих концах ассоциации. На рис. 3.5 стрелок нет; в язы­ке UML эта форма применяется либо для обозначения двунаправлен­ной ассоциации, либо когда направление отношения не показывается. Я предпочитаю обозначать двунаправленную ассоциацию с помощью двойных стрелок.

Рис. 3.5. Использование глагола (own - владеть) в имени ассоциации

Реализация двунаправленной ассоциации в языке программирования часто представляет некоторую сложность, поскольку необходимо обес­печить синхронизацию обоих свойств. В С# для реализации двуна­правленной ассоциации я делаю следующее:

class Car... public Person Owner {

get {return____ owner;}

set {

if (_owner!= null) __ owner.friendCars().Remove(this);

__ owner = value;

if (_owner!= null)__owner.friendCars(),Add(this);


}

}

private Person _owner;

class Person …

public IList Cars {

get {return ArrayList.ReadOnly(_cars); }

}

public void AddCar(Car arg) {

arg. Owner = this;

}

private IList _cars = new ArrayListQ;

internal IList friendCars() {

//должен быть использован только Car.Owner

return _cars;

}

….

Главное - сделать так, чтобы одна сторона ассоциации (по возможно­сти с единственным значением) управляла всем отношением. Для это­го ведомый конец (Person) должен предоставить инкапсуляцию своих данных ведущему концу. Это приводит к добавлению в ведомый класс не очень удобного метода, которого здесь не должно было бы быть в действительности, если только язык не имеет более тонкого инстру­мента управления доступом. Я здесь употребил слово «friend» (друг) в имени как намек на C++, где метод установки ведущего класса дей­ствительно был бы дружественным. Как и большинство кода, работа­ющего со свойствами, это стереотипный фрагмент, и поэтому многие разработчики предпочитают получать его посредством различных спо­собов генерации кода.

В концептуальных моделях навигация не очень важна, поэтому в та­ких случаях я не показываю каких-либо навигационных стрелок.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: