2013-08-16 104 views
0

我有點不知所措,管理一個複雜的PHP的應用程序。在過去,我使用靜態方法來處理'utils'類,但是我正在編寫一個新的應用程序,並且我想盡可能以最高標準進行編碼,所以我儘可能地避免使用它們。保持可測試性等對象工廠

我已經看過依賴注入,但我打算創建一個幫助類的「庫」(所以說),我可以放入和退出項目沒有太多麻煩。我的問題是,因爲我可能會有五六個,我真的不想設置用戶需要將所有這些對象傳入的構造。

我的研究帶來了我的工廠 - 和我創建這樣的野獸,但我真的不知道這是去了解事情的正確方法。它會有點像這樣...

class Create { 

private static $validation = null; 
private static $helper = null; 
private static $html = null; 
private static $form = null; 
public static $user = null; 
public static $db = null; 

// -------------------------------------------------------------- 
// Initialize 
// -------------------------------------------------------------- 

public static function load($object, $options, $dependencies = array('html', 'helper', 'db', 'user')) { 

    // Create specified object (without constructor) 
    // PHP version < 5.4 
    $$object = self::createInstanceWithoutConstructor($object); 

    // Inject specified options into new object 
    foreach($dependencies as $dependency): 
     if(is_null(self::$$dependency)): self::$$dependency = new $dependency; endif; 
     $$object->$dependency = self::$$dependency; 
    endforeach; 

    // Now call the constructor 
    // PHP version < 5.4 
    if(method_exists($$object, '__construct')): 
     $$object->__construct($options); 
    endif; 

    return $$object; 

} 

// -------------------------------------------------------------- 
// Create Instance of Object Without Calling it's Constructor 
// -------------------------------------------------------------- 
// Workaround for PHP version < 5.4 
// This will be updated to use 
// ReflectionClass::newInstanceWithoutConstructor 
// when 5.4 is more freely supported 
// -------------------------------------------------------------- 

private static function createInstanceWithoutConstructor($class) { 

    $reflector = new ReflectionClass($class); 
    $properties = $reflector->getProperties(); 
    $defaults = $reflector->getDefaultProperties(); 

    $serealized = "O:" . strlen($class) . ":\"$class\":".count($properties) .':{'; 
    foreach ($properties as $property){ 
     $name = $property->getName(); 
     if($property->isProtected()){ 
       $name = chr(0) . '*' .chr(0) .$name; 
      } elseif($property->isPrivate()){ 
       $name = chr(0) . $class. chr(0).$name; 
      } 
      $serealized .= serialize($name); 
      if(array_key_exists($property->getName(),$defaults)){ 
       $serealized .= serialize($defaults[$property->getName()]); 
      } else { 
       $serealized .= serialize(null); 
      } 
     } 
    $serealized .="}"; 

    return unserialize($serealized); 

} 

// -------------------------------------------------------------- 
// Create User 
// -------------------------------------------------------------- 

public static function User($options = array()) { 

    $user = self::load(__FUNCTION__, $options); 
    return $user; 

} 

// -------------------------------------------------------------- 
// Create Page 
// -------------------------------------------------------------- 

public static function Page($options = array()) { 

    $page = self::load(__FUNCTION__, $options); 
    return $page; 

} 

// -------------------------------------------------------------- 
// Create Form 
// -------------------------------------------------------------- 

public static function Form($name, $method = 'POST', $action = null, $attributes = array()) { 

    // Check to see if form was submitted 
    // If so, get form object, otherwise create new form object 
    if(isset($_POST[$name])): 
     $form = unserialize($_SESSION['formObj']); 
     $form->errors = array(); 
     $form->rule = $form->rule; 
     $form->labels = $form->labels; 
     $form->errors = $form->errors; 
    else: 
     $form = self::load(__FUNCTION__, array(), array('html', 'validation')); 
     $form->name = $name; 
    endif; 

    // Open the form 
    $form->open($method, $action, $attributes); 

    return $form; 

} 

} 

所以它擁有用於創建各種物體獨立的功能,有傳遞,除非依賴性明確設置默認的選擇。現在

,我真的不知道,如果這是一個很好的辦法,從更多的研究,我收集它可能是一個更好的主意,有一個工廠爲每個負責該類創建對象類。這是更正確的方法嗎?如果是這樣,那麼這些工廠方法(不知道這是正確的術語嗎?)只是靜態的,可以在任何地方調用,或者他們只是創建新對象然後傳遞它們的普通方法?這是否也需要擴展一個包含已創建對象的「工廠」類?

希望一切都有道理,任何和所有的幫助將不勝感激。

你的,

混淆N00b。

+4

只是一個小提示:名稱爲動詞的類要麼命名不正確,要麼是 - 經常 - 嚴重封裝。動作(動詞)不是對象(名詞)。 – str

+0

如果你的課程有太多的依賴關係,那麼這是一個明確的標誌,你的班級有太多的責任。而不是增加一些魔法,而應該嘗試修復這些類。另外,這個'$$對象'的意義是什麼?爲什麼你不能把它稱爲'$ instance',因爲它是一個局部變量,它的名字在函數外面沒有任何作用。 –

+0

我不認爲我的課程有太多的責任,這是我希望我的'幫手'課程可以在整個應用程序中輕鬆使用。我只是在試圖避免靜態類時發現難以允許。 至於$ object - $ instance可能會更有意義tbh。感謝指針。 – 0Neji

回答

3

看着你的代碼和閱讀你的文章,我覺得你是過分複雜的東西。

您不需要專注於什麼是「正確」的做法。做某件事的正確方法是最適合您的情況的方式。看看你需要做什麼,展望未來(但不是太遠!),並試圖找到一個沒有過度設計的解決方案,但給你的空間增長。

我說的不是太遙遠的未來,因爲開發商往往傾向於在他們的設計太趕了上來,努力計劃每一個可能的不測,和你結束了一個怪物是不可能維持。

如果包含在一個靜態類是爲你工作,而你不盡快預見這個任何時間在任何重大問題,爲什麼你需要保持設計了一系列工廠的功能呢?其中最難的事情要學會做的是走面向未來的設計,只是做事情:)

+0

我喜歡這個答案,但我只是有這種感覺,我應該期待學習這種模式(這不僅僅是一種愛好!)。最適合我的將是失去工廠,但依靠靜態類,可以很容易地投入到多個項目沒有問題。儘管如此,這更多的是方便和易用的答案。我寧願確定工廠模式,然後決定,但我仍然找到任何能夠以一種易於理解的方式真正表明正確的事情要做的事情。 – 0Neji

+1

那麼,學習的唯一方法就是犯錯:)做你覺得你需要的東西!但是,要知道實現一個模式沒有一個正確的方法,它們只是解決複雜問題的建議。使用它們來獲得靈感,但適合你的情況。如果你設計的東西是可移植的,那麼現在唯一真正重要的是接口。接口後面的所有內容都可以在以後輕鬆更改。工廠很方便,因爲它們在更簡單的界面後面隱藏了來自調用者的創建細節,所以稍後更容易進行更改。 – verv

0

你所列出的是看起來像壞企圖使服務定位器之間的界線。這是一種註冊模式。 每個班級都應該有一定的目的。 因此,使ServiceLocator類和工廠類/方法的數量返回實例。然後在應用程序啓動時將它們設置爲ServiceLocator。