Я хотел бы знать, как лучше всего обращаться с двунаправленной ассоциацией в О.П. я имею нашел несколько решений в Google и SO но у каждого из них, кажется, есть недостаток. Язык не имеет значения, но давайте использовать PHP, чтобы проиллюстрировать, что я имею в виду:
Допустим, у меня простые штаты .. [1..n] .. Городская ассоциация:
public class State {
public $cities;
public function add_city($city) {}
}
public class City {
public $state;
public function set_state($state) {}
}
ОСУЩЕСТВЛЕНИЕ № 1:
public class State {
public $cities;
public function add_city($city) {
$this->cities[] = $city;
$city->state = $this;
}
}
public class City {
public $state;
public function set_state($state) {
$this->state = $state;
$state->cities[] = $state;
}
}
Две проблемы с этой реализацией:
ОСУЩЕСТВЛЕНИЕ № 2:
public class State {
public $cities;
public function add_city($city) {
$this->cities[] = $city;
if ($city->state != $this) {
$city->set_state($this);
}
}
}
public class City {
public $state;
public function set_state($state) {
$this->state = $state;
if (!in_array($this, $state->cities)) {
$state->add_city($this);
}
}
}
Немного лучше, чем # 1, но функция «set_state» должна вызывать «in_array», который на языке must — O (n) (превращение быстрой операции O (1) в операцию O (n).)
ОСУЩЕСТВЛЕНИЕ № 3:
public class State {
public $cities;
public function add_city($city, $call_the_other_function = true) {
$this->cities[] = $city;
if ($call_the_other_function) {
$city->set_state($this, false);
}
}
}
public class City {
public $state;
public function set_state($state, $call_the_other_function = true) {
$this->state = $state;
if ($call_the_other_function) {
$state->add_city($this, false);
}
}
}
Реализация №3 очень эффективна, но довольно уродлива (из-за отсутствия лучшего термина) из-за дополнительного необязательного параметра
В любом случае, если у кого-то есть идея, что такое «Правильный путь», я хотел бы знать.
РЕДАКТИРОВАТЬ:
Если это возможно, я бы хотел решение:
Я бы попробовал использовать конструктор таким образом, когда вы устанавливаете город, вы можете напрямую передать его состояние.
public class State {
private $cities;
public function add_city($city) {
$this->cities[] = $city;
}
}
public class City {
private $state;
function __construct($state) {
$state->add_city($this)
$this->state=$state
}
}
Во всех ваших предложениях Сити знает о методах в государстве или наоборот. Что, если вы ввели третий класс, отвечающий за связь городов с государствами, например LocationService
с одним методом, таким как linkCityToState
? С этим вы могли бы позже расширить его linkCityToCountry
или какая-то продвинутая логика, такая как getPostalCodeFromApi
,
Если вы беспокоитесь о производительности, превратите свой список в хэш-набор, который снизит сложность поиска до простого O(log n)
,
Также в вашей реализации # 1 у вас есть city->cities
…?
В любом случае, я бы никогда не выбрал решение № 3, если бы не программировал алгоритмы сжатия, драйверы, массивный запросы к базе данных и т. д.