2013-03-27 5 views
3

Не уверен, что мой заголовок правильный, потому что я даже не уверен, что использую правильные условия.Зависимость впрыска и/или заводская схема

У меня есть класс, который имеет свойство, являющееся объектом. При настройке этого свойства объект должен быть создан. Мой вопрос: как мне это сделать без жесткой связи?

Пример:

class A 
{ 
    protected $_depending; 

    protected $_somePropertyObject; 

    public function __construct(\Lib\Dependency $depending) 
    { 
     $this->_setDepending($depending); 
    } 

    protected function _setDepending(\Lib\Dependency $depending) 
    { 
     $this->_depending = $depending; 
    } 

    public function setSomeProperty($someProperty) 
    { 
     // I want to prevent this 
     $this->_somePropertyObject = new \Lib\some\Object($someProperty); 
    } 
} 

Я мог бы просто передать нужный объект с помощью конструкции, но то, что происходит более необходимы?

Если, если я правильно понял заводскую модель, что бы это изменило? Мне все равно нужно было бы создать объект где-нибудь? Не сам объект, а фабрика. Снова плотная муфта? Кажется бесконечным для меня. Когда re-factoring class (es) он, однако, изолирован, где и как производятся класс (ы).

Если я установил функцию setSomeProperty только для принятия \ Lib \ some \ Object, то все равно должен быть создан родительский объект, который передает его для начала. Кажется, только сдвинуть место размещения, где оно создано?

Надеюсь, я достаточно ясен в том, что я пытаюсь задать.

Заранее благодарен!

EDIT То, что я прошу, это последовательность того, что создано, когда, где, почему.

ответ

4

Цель завода в моделях инжекторной зависимости является создание экземпляров другого экземпляра, без этого другого экземпляра нужно знать, как производить его ,

В основе ядра «фабрика» - это просто объект-возврат: что-то, возвращающее экземпляр при вызове.

Это легче увидеть на более способных языках. Например, в классах Python вызываются (нет оператора new), а вызов класса создает экземпляр класса. Таким образом, классы могут быть их собственными фабриками, если класс не требует аргументов. Аналогично любая функция нулевого аргумента, возвращающая экземпляр, может считаться фабрикой. Это делает инъекцию зависимостей очень четкой и свободной от шаблонов.

В более жестких языках (традиционная типизация Java/C++/C#, или где классы или функции не являются полностью первоклассными, как в PHP), вам необходимо замаскировать инъекцию зависимостей за «шаблоном», потому что "design patterns" are missing language features. В PHP 5.3+ вы можете использовать закрытие в качестве фабрики, или вы можете перейти на путь Java/C# и определить FactoryInterface и новый класс для каждой фабрики.

Например, с классом, вы можете сделать это:

class Aprime extends A 
{ 
    public function setSomeProperty($somePropertyFactory) 
    { 
     $this->_somePropertyObject = $somePropertyFactory(); 
    } 
} 

В этом классе setSomeProperty требует нулевого аргумента вызываемого «завод», который можно произвести так:

$other_dep_factory = function(){ return new SomeOtherClass(); }; 

Или так:

class ClassFactory { 
    function __construct($classname, $args=array()) { 
     $this->class = new ReflectionClass($classname); 
     $this->args = $args; 
    } 

    function __invoke() { 
     return $this->class->newInstanceArgs($this->args); 
    } 
} 

$other_dep_factory = new ClassFactory('SomeOtherClass'); 

до PHP 5.3, вам нужно сделать это похоже на Java:

interface IObjectFactory { 
    function getObject(); 
} 

// this B-and-D interface is optional 
// it has no body because PHP doesn't support 
// type-hinting return values 
interface ISomeOtherClassFactory {} 


class SomeOtherClassFactory implements ISomeOtherClassFactory { 
    function getObject() { 
     return new SomeOtherClass(); 
    } 
} 

class Aprime extends A 
{ 
    public function setSomeProperty(ISomeOtherClassFactory $somePropertyFactory) 
    { 
     $this->_somePropertyObject = $somePropertyFactory->getObject(); 
    } 
} 


$other_dep_factory = new SomeOtherClassFactory(); 
$myAprimeObject->setSomeProperty($other_dep_factory); 

Итак, когда вы используете завод? Всякий раз, когда объект должен создавать другой объект. Если объекту нужно только , используйте другой объект, просто перейдите в экземпляр.

+0

Но где я могу создать этот заводский объект? Должен ли я передать его как зависимость? Предпочтительно без статичности. – John

+0

Создайте его, прежде чем создавать то, что ему нужно. –

+0

Тогда его еще крепко связали? Пример: public function something() {$ factory = new factory(); }? Не говорить о сеттерах? – John

0

Мне нравится использовать Factory Pattern, когда вам нужно собрать «информацию», чтобы создать объект, который хранится в $ _somePropertyObject. Например, предположим, что вам нужно назначить значения некоторым свойствам для его создания или запустить несколько методов сразу после его создания.

Кроме того, вы захотите рассмотреть вопрос о необходимости изменения дерева наследования позднее. Если теперь вы можете назначить $ _somePropertyObject a \ Lib \ some \ Object, вы можете захотеть, что вы можете легко поменять его на \ Lib \ some \ FancyObject позже. Если вы используете Dependency Injection, вы можете легко заменить подтипы.

Вот праймер: http://net.tutsplus.com/tutorials/php/the-whens-and-whys-for-php-design-patterns/

Кроме того, также: https://stackoverflow.com/a/2083455/1121827

+0

На заводе вы делаете, где и как вы: создаете, определяете и собираете информацию? С самого первого класса, который называется. – John

+0

Посмотрите свое редактирование. Мне все еще интересно, где можно создать сам заводский объект? – John