2009-06-29 4 views
7

У меня есть класс с функцией завода-шаблоном в нем:инстанцирование дочерних классов от родительского класса (PHP)

abstract class ParentObj { 
    public function __construct(){ ... } 
    public static function factory(){ 
     //returns new instance 
    } 
} 

мне нужны дети, чтобы иметь возможность вызвать функцию фабрики и возвращает экземпляр вызова класс: $child = Child::factory(); и предпочтительно без переопределения заводской функции в дочернем классе.

Я пробовал несколько разных способов достижения этого безрезультатно. Я предпочел бы держаться подальше от решений, которые используют отражение, например __CLASS__.

(Я использую PHP 5.2.5, если это имеет значение)

ответ

10

Если вы можете перейти на PHP 5.3 (released 30-Jun-2009), проверьте late static binding, которые могли бы обеспечить решение:

abstract class ParentObj { 
    public function __construct(){} 
    public static function factory(){ 

     //use php5.3 late static binding features: 
     $class=get_called_class(); 
     return new $class; 
    } 
} 


class ChildObj extends ParentObj{ 

    function foo(){ 
     echo "Hello world\n"; 
    } 

} 


$child=ChildObj::factory(); 
$child->foo(); 
+0

Я играл с RC4 на минуту, так что я постараюсь немного кода в ближайшее время, если никто не ступает в то же время ... –

+0

LSB кажется быть лучшим решением, которое я могу найти самостоятельно. До тех пор, пока я не обновляюсь, лучшее, что я могу придумать, - либо передать дочернее имя на factory(), либо определить имя как свойство и захватить его с завода() –

+0

Согласно руководству PHP, есть функция под названием ' get_called_class() ', который работает как' __CLASS__' http://us.php.net/manual/en/function.get-called-class.php –

0

В моей скромное мнение, что вы пытаетесь сделать, не имеет смысла.

Узор завод будет работать так:

abstract class Human {} 

class Child extends Human {} 
class Fool extends Human {} 

class HumanFactory 
{ 
    public static function get($token) 
    { 
     switch ($token) 
     { 
      case 'Kid' : return new Child(); 
      case 'King': return new Fool(); 
      default : throw new Exception('Not supported'); 
     } 
    } 
} 

$child = HumanFactory::get('Kid'); 
+0

Ну, это полномасштабный заводской шаблон. Я просто имел в виду статический метод обхода оператора 'new' и обеспечения читаемости и привязки к дочерним классам. –

+0

Почему вы хотите обойти нового оператора? –

+1

, чтобы использовать ваш пример, новый Child() -> foo() не работает. добавив метод «factory» (как я его использую), вы можете сделать Child :: factory() -> foo() -> bar(), что более читаемо (IMHO), чем разбить его на несколько строк. Я думаю, это вопрос мнения, и, честно говоря, ваша реализация фабрики является полезной. Просто не для того, что я ищу. –

Смежные вопросы