2015-10-15 73 views
2

我想知道在O.O.P中處理雙向關聯的最佳方法。我有在Google和SO上找到了多個解決方案,但它們中的每一個似乎都有缺點。語言是不相關的,但讓我們使用PHP來說明我的意思:在OOP中處理雙向關聯的最佳方法

比方說,我有一個簡單的國... [1..1] ..市協:

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; 
    } 
} 

的兩個問題,實現有:

  • 「$統計e「和」$ 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); 
     } 
    } 
} 

執行#3是非常有效的,但是是一種「醜」(因爲缺乏一個更好的詞),因爲額外的可選參數的

無論如何,如果任何人有任何想法什麼是「正道「(tm)是,我想知道。

編輯: 如果可能的話我想一個解決方案:

  • 不使用另一個類
  • 不知道其中的對象創建的順序(即不是「構造」的解決方案)
+2

「正確的方式(tm)」問題是無法用於Stackoverflow的,因爲它們傾向於生成基於意見的答案。請查閱http://stackoverflow.com/help/on-topic以查看您應該不應該詢問的內容。 –

+0

原諒我,但我很困惑你的第一次實施。爲什麼這些變量需要公開? 「朋友」類可以在其他班上使用公共方法,難道不是嗎? – Jacob

+0

除了@TimLewis所說的,或許你的問題會更適合[程序員StackExchange](http://programmers.stackexchange.com/):) – Jacob

回答

0

在您的所有建議中,城市知道州內的方法,反之亦然。如果你引入了第三類負責連接城市和州,如LocationService與一種方法,如linkCityToState?有了這個,你可以稍後用linkCityToCountry或者一些高級邏輯如getPostalCodeFromApi來擴展它。

如果您擔心性能,請將您的列表轉換爲哈希集,這會將查找複雜性降低至僅爲O(log n)

另外在你的實現#1中你有city->cities ...?在任何情況下,除非我正在編程壓縮算法,驅動程序,海量數據庫查詢等,否則我絕對不會解決方案#3。

+0

我的錯誤;我應該在我的問題中添加「不使用任何額外的類」。 – d08z

+0

Welp循環引用通常通過引入第三類來解決。 –

+0

誠實的問題:爲什麼你永遠不會使用解決方案#3? – d08z

2

我想嘗試使用一個構造函數,這樣,當你安置一個城市時,你可以直接傳遞它的狀態。

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 
    } 
} 
+0

如果狀態還不存在(如果狀態不存在,將在以後創建並鏈接)城市是否被創造? – d08z

+1

你需要指定你的用例,然後代碼將會出現。 – NicolaSysnet

+0

城市與州之間存在依賴關係:一個城市恰好屬於一個州,一個州包含零個或多個城市。這種依賴需要一個城市在其擁有狀態之後創建。答案用代碼表示這種說法;它也提供了屬性的正確封裝。 – axiac