我希望知道处理面向对象编程中双向关联的最佳方式。我在Google和SO上找到了多种解决方案,但每一种似乎都有缺陷。语言不重要,但让我们用PHP来说明我的意思:
假设我有一个简单的州..[1..n]..城市关联:
假设我有一个简单的州..[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;
}
}
这种实现方法存在两个问题:
- "$state"和"$cities"必须是公共的(这样任何人都可以添加城市而不需要使用公共函数add_city...)。大多数语言中没有“友元类”的概念。
- 在添加之前,公共函数可能需要执行某些操作。
实现方法 #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”函数,大部分语言中这是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);
}
}
}
第三种实现方法非常有效,但由于额外的可选参数而有点“丑陋”(缺乏更好的术语),
无论如何,如果有人知道“正确的方式”(tm)是什么,我想知道。
编辑: 如果可能的话,我希望有一个解决方案:
- 不使用另一个类
- 不知道对象创建的顺序(即不是“构造函数”解决方案)