What's the best way to implement a factory method for an extended class?
考虑以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 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" Specifically, a bus!"; } } class Car extends Vehicle { public function drive(){ parent::drive(); echo" Specifically, a car!"; } } // Drive a car Car::create()->drive(); // Drive a bus Bus::create()->drive(); |
我在Vehicle类中实现了一个工厂"create"方法,该方法允许我获取要使用的类的实例。
我尝试使用"return new self();",但它总是返回车辆的一个实例,所以我使用eval。
问题:是否有非eval方法来实现create()方法,以便:
- 它返回正在使用的类的实例
- 它不需要在每个扩展类上实现create()。
使用static而不是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?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" Specifically, a bus!"; } } $b = Bus::create(); $b->drive(); |
印刷品
1 2 | I am a Vehicle! Specifically, a bus! |
(沃尔克打败了我,但这有点变化)
等等,你为什么要这样做?不会:
1 2 3 4 5 | public static function create() { $class = get_called_class(); return new $class(); } |
工作?
最好的方法是将工厂方法从混凝土类型中移入自己的工厂类中。这样,您不仅可以更轻松地处理这个问题,而且还可以轻松地用另一个工厂替换该工厂。
我假设您知道对象继承是如何工作的,所以您不必处理任何不太直接的静态问题,并且开始以相当快的速度站在某个方面。