2011-01-06 39 views
1

我想確保我的應用程序強制執行依賴注入,但我進入有點鹹菜......PHP OOP ::弄不清工廠類和傳球對象構造

class Factory { 

public $sessionId; 
public $config; 
public $lib; 

function __construct() { 
    $this->getSessionId(); 
} 

function getSessionId() { 
    if (isset($_COOKIE['sk'])) { 
     $this->sessionId = trim($_COOKIE['sk']); 
    } else { 
     $sm = $this->createSessionManager(); 
     $this->sessionId = trim($sm->getNewKey()); 
     setcookie("sk", $this->sessionId, time() + 3600 * 3, "/"); 
     setcookie("vb", 0, 0, "/"); 
    } 

} 

function createBasket() { 
    $t = $this->createTicket(); 
    $co = $this->createContribution(); 
    $cfg = $this->createConfig(); 
    $basket = new Basket($t, $co, $cfg); 
    return $basket; 
} 

function createTicket() { 
    $sm = $this->createSessionManager(); 
    $cfg = $this->createConfig(); 
    $ticket = new Ticket($this->sessionId, $sm, $cfg); 
    return $ticket; 
} 

.. .. }

首先,我想知道我是否以正確的方式接近事情。一個例子瀏覽器畫面 - 通過瀏覽器叫做 - 將是:

function __autoload($class_name) { 
    include 'classes/' . $class_name . '.class.php'; 
} 

$factory = new Factory; 

$performance = $factory->createPerformance(); 
$pno = (isset($_GET['pno']) ? $_GET['pno'] : 0); 
print $performance->displayHtmlListing($pno); 

我的其他問題/問題是有關我如何防止在對象A需要對象B,一個「抓22」的局面 - 在極少數情況下 - 將需要對象A 。

一個例子,在工廠類:

function createParser() { 
    $am = $this->createApiManager(); 
    $parser = new Parser($am); 
    return $parser; 
} 

解析器對象被傳遞對象插入的構造,以滿足在業務邏輯它的依賴性。它的工作是讀取文件請求,如果滿足某些條件,它需要抓住$ am對象(APIManager)併發出對API的請求。問題是,APIManager通過解析器對象傳遞所有請求,並且我無法輕鬆地移除對解析器的依賴關係,而不會破壞業務規則或添加冗餘條件代碼。

想知道如果有人對如何解決這個問題有一些想法?

謝謝,詹姆斯

UPDATE:

的依賴問題

位的詳細信息:

ApiManager.caller() - 它的工作是走下車來的API URL發送GET變量,檢索結果。這個調用者()方法幾乎被所有的類使用(也許這是一個很好的理由,因爲它是超類,並擴展了需要它的類)。

調用方()的部分責任是檢查正在進行的API調用。如果滿足某個條件,則需要停止並調用SessionManager.getNewSession(),該SessionManager.getNewSession()將返回到相同的API並檢索值。只有當這完成時,才能完成原始請求(在調用方()中)。

問題是SessionManager.getNewSession()也使用caller()。

回答

3

這只是恕我直言,但有大量名稱包含「經理」,「上下文」,「解析器」等類的類是一種代碼味道。我並不是說這些類肯定是錯的 - 實際上每個應用程序都有它們。但是仔細想想 - 解析器是一件你擁有的東西,還是解析一個對象所做的事情?有沒有一個真實世界的人與「API經理」的標題?他是否與會話管理員一起出去問問你關於你的TPS報告?等等

想想你的班級設計 - 我並不是說它是「錯誤的」 - 因爲我沒有看到它,它無論如何都是主觀的 - 但是你的班級是爲真實世界的實體建模的,還是他們是在建模可以在實體上執行的行爲嗎?或者,更糟的是,他們是在建模某種任意的工作流程嗎?你們的班級是否都有明確規定的責任,而不是試圖做一些與他們無關的瘋狂事情?

基本上,你遇到了這個問題,因爲你的類設計並不是最優的。特別是,如果一個類的實例需要另一個類反之亦然的實例才能正常工作,你可能會重新考慮從你的設計中獲益。

更新響應詹姆斯的更新

ApiManager.caller() - 它的工作是走下車來的API URL發送GET變量,並檢索結果。

OOP的一個想法是,類表示實體(名詞),方法表示動作(動詞)。 ApiManager這裏是一個實體(樣一個抽象的,但我們會用它去),但caller()不是一個行動 - 即你不能「來電顯示」的東西。你可以但是call()東西 - 我想在ApiManager的上下文中,這將「調用」API。我知道這只是兩個小小的字母,但它對於ApiManager所做的事情的心理概念有很大的不同。

這個調用者()方法幾乎被所有的類使用(也許這是一個很好的理由,因爲它是超類,並擴展了需要它的類)。

繼承最好用來支持多態,而不是代碼共享 - 我不會那樣做的......調用者()責任

部分是檢查正在作出哪些API調用。如果滿足某個條件,則需要停止並調用SessionManager.getNewSession(),該SessionManager.getNewSession()將返回到相同的API並檢索值。只有當這完成時,才能完成原始請求(在調用方()中)。

一個問題是,caller()不應該有責任,因爲它應該是一個動作(例如call()),而不是一個東西。行動不能承擔責任。它應該做一些事情,最好是簡單的事情。在與ApiManager的主意,因爲這事,call()作爲ApiManager做一個動作保持一致,這裏是我怎麼可能期望非常最低限度的示例的ApiManager工作:

class ApiManager { 

    private $session; 
    private $url; 

    // You'll probably need to set up the object differently; 
    // this is just an example.... 
    public function __construct($url) { 
     $this->setURL($url); 
    } 

    function call() { 
     if ($this->session is expired) { 
      // instead of calling SessionManager.getNewSession() here, 
      // why not just fold the session management functionality 
      // into ApiManager? They both use the same API, after all... 
      $session = $this->getNewSession(); 
     } 
     // do your call & return the response 
    } 

    public function setURL($url) { 
     $this->url = $url; 
    } 

    private function getNewSession() { 
     // get a new session 
     $this->session = $my_new_session; 
    } 

} 

你會發現,上面課程中的所有方法都是行爲,他們都做了一些事情。錦上添花的是,不再需要擔心SessionManager的依賴注入,因爲它不再存在!畢竟,API會話確實只有ApiManager需要知道的東西,不是嗎? :)

+0

>「如果一個類的實例,需要另一個類,反之亦然正常工作的實例」 - 專題起動器使用依賴注入,其主要思想是將特定的類實例注入依賴類 – galymzhan 2011-01-06 18:39:03