PHP从子类工厂方法调用超类工厂方法

时间:2011-12-21 01:08:59

标签: php subclass factory-pattern superclass

我正在编写一个带有子类的php应用程序,因为我想有多种方法来创建一个对象,我正在做不同的工厂方法而不是多个构造函数。

我有User工厂方法

User::from_id
User::from_netid

我有几个User的子类。我以前调用了父超级构造函数,但是当我切换到工厂方法时,构造函数不存在。

我有StudentUser的子类。为了使它工作,我不得不将User::from_id中的几乎所有超类工厂代码复制到load_by_id,因为在这种情况下实例已经存在:

// In Student.php - Student extends User
public static function from_id_and_course($id, $course){
    $instance = new self();
    $instance->load_by_id($id);
    $instance->course = $course;
    ...
}

我想从子类中调用超类工厂方法作为起点,然后继续添加其他字段。像这样......

$instance = User::from_id($id);

$instance = Student::from_id($id);

但在这些情况下它会给我一个User个对象,我需要一个Student个对象。我能做到这一点的唯一方法就是做$instance = new self()

如何从子类调用超类工厂方法作为创建新子类工厂方法的起点?

2 个答案:

答案 0 :(得分:5)

你的问题是:

$instance = new self();

self是指定义方法的类,而不是调用者:

  • 调用Student::from_id()时,如果它不存在,则会回退到User::from_id()
  • User::from_id()中,self是指User,而不是Student

您必须使用late-static bindings

$instance = new static();

然而,就像我一直这样,我强烈建议不要这样做。您最好使用对象范围而不是静态范围。更容易扩展,虚假或嘲笑,以及顺便进行测试。

没有错:

$user = new User;
$user->from_id($id);

$student = new Student;
$student->from_id($id);

......它实际上更好。

答案 1 :(得分:1)

如果您使用的是PHP 5.3或更高版本,则可以使用现有的Late Static Bindings

class User
{
  public static function from_id($id)
  {
    // factory
    $object = new static();

    // setup

    // return
    return $object;
  }
}

class Student extends User { }

$student = Student::from_id($id); // $student should be of class Student

注意 - 你可能最好设置一个完整的工厂类来进行模拟/测试/理智......