【问题标题】:Object Factories对象工厂
【发布时间】:2013-08-16 12:15:12
【问题描述】:

管理一个复杂的 php oop 应用程序让我有点不知所措。过去,我为我的“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。

【问题讨论】:

  • 只是一个小提示:名称为动词的类要么命名错误,要么 - 大多数情况下 - 封装错误。动作(动词)不是对象(名词)。
  • 如果你的类有太多的依赖,那么很明显,你的类有太多的责任。与其添加一些魔法,不如尝试修复这些类。另外,$$object 的意义何在?为什么不能直接叫它$instance,因为它是一个局部变量,它的名字在函数之外没有任何影响。
  • 我不认为我的类有太多责任,我希望我的“帮助”类在整个应用程序中都可以轻松使用。我只是发现在尝试避免静态类时很难允许。至于 $object - $instance 可能更有意义。谢谢指点。

标签: php oop factory


【解决方案1】:

看着你的代码和阅读你的帖子,我觉得你把事情复杂化了。

您无需专注于做某事的“正确”方式。做某事的正确方法是最适合您给定场景的方法。看看你需要做什么,展望未来(但不要太远!!),并尝试找到一个没有过度设计但给你成长空间的解决方案。

我说的未来不会太远,因为开发人员往往过于专注于他们的设计,试图为每一种可能的可能性做计划,而你最终会得到一个无法维护的怪物。

如果静态类中包含的一系列工厂函数正在为您工作,并且您不会很快预见到任何重大问题,那么您为什么需要继续设计?学习做的最难的事情之一就是在为未来设计和完成事情之间走一条线:)

【讨论】:

  • 我喜欢这个答案,但我只是觉得我应该学习这种模式(这不仅仅是一种爱好!)。对我来说最好的方法是失去工厂,但依靠可以轻松放入多个项目而没有问题的静态类。不过,这更像是一个方便且易于使用的答案。我更愿意确定工厂模式,然后再决定,但我仍然要找到任何能够以易于理解的方式真正表明正确做法的东西。
  • 嗯,学习的唯一方法就是犯错 :) 做你觉得你需要的事!但是,要知道没有一种正确的方法来实现模式,它们只是解决复杂问题的建议。使用它们来获得灵感,但要根据您的情况调整它们。如果您正在设计可移植的东西,那么现在唯一真正重要的是界面。界面后面的所有内容都可以在以后轻松更改。工厂很方便,因为它们在更简单的界面后面对调用者隐藏了创建的细节,因此以后更容易更改。
【解决方案2】:

您列出的内容看起来像是制作服务定位器的错误尝试。这是一种注册表模式。 每个班级都应该有特定的目的。 因此,使 ServiceLocator 类和工厂类/方法的数量返回实例。然后在应用程序启动时将它们设置为 ServiceLocator。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多