2013-08-16 105 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。