为扩展类实现工厂方法的最佳方法是什么?

时间:2012-10-19 21:02:42

标签: php

请考虑以下代码:

class Vehicle {

    /**
    * Create a new instance of Vehicle
    * 
    * @return Vehicle
    */
    public static function create(){

        return eval( "return new " . get_called_class() . '();' );
        // return self(); would always return Vehicle reg ardless

    }


    public function drive(){

        echo "I am a Vehicle!";

    }

}

class Bus extends Vehicle {

    public function drive(){

        parent::drive();

        echo "\nSpecifically, a bus!";

    }

}


class Car extends Vehicle {

    public function drive(){

        parent::drive();

        echo "\nSpecifically, a car!";

    }

}

// Drive a car
    Car::create()->drive();

// Drive a bus
    Bus::create()->drive();

我在Vehicle类中实现了一个工厂“create”方法,它允许我获取我想要使用的类的实例。

我尝试过使用“return new self();”但是这总是返回一个Vehicle的实例,所以我使用了eval。

问题:是否有非eval方法来实现create()方法,以便:

  • 它返回您正在使用的类的实例
  • 它不需要在每个扩展类上实现create()

3 个答案:

答案 0 :(得分:4)

使用static代替self,例如

<?php
class Vehicle {
    public static function create(){
        return new static();
    }

    public function drive(){
        echo "I am a Vehicle!";
    }
}

class Bus extends Vehicle {
    public function drive(){
        parent::drive();
        echo "\nSpecifically, a bus!";

    }
}

$b = Bus::create();
$b->drive();

打印

I am a Vehicle!
Specifically, a bus!

答案 1 :(得分:1)

(VolkerK击败我,但这有轻微的变化)

等等,为什么你需要eval()?不会:

public static function create() {
    $class = get_called_class();

    return new $class();
}

工作?

答案 2 :(得分:0)

最好的方法是将工厂方法从混凝土类型中移出并转移到它自己的工厂类中。然后,您不仅可以更轻松地处理此问题,还可以轻松地将工厂更换为其他工厂。

我假设您知道对象的继承是如何工作的,所以您不必处理任何不那么直接的静态并且开始以某种方式站得很快。