2012-01-13 12 views
7

Próbuję zbudować prostą usługę do renderowania różnych typów stron. Podstawową koncepcją jest coś takiego:Strategia w Symfony2

$somePageType = new PageType(...); 
$this->get('page.service')->render($somePagetype); 

... który zostałby zaprojektowany jako Strategy pattern. Typy stron implementowałyby interfejs za pomocą metody render i wywoływałyby go w postaci page.service. Problem polega na tym, że chciałbym używać Doctrine w klasach typu strony. Jakie są moje opcje tutaj? Chciałbym uniknąć tworzenia usługi dla każdej z tych klas. Czy to w ogóle jest możliwe? Czy można uczynić je pojemnymi, nie będąc usługami? Być może w przyszłości niektóre typy stron mogą wymagać czegoś więcej niż tylko Doctrine, więc muszę o tym pamiętać.

Odpowiedz

1

Przyjmuję, że PageType jest przykładem klasy strategii. W takim przypadku można wprowadzić zależności przez page.service i nie trzeba definiować strategii jako usług.

Każda strategia prawdopodobnie zależy od różnych obiektów i dlatego domyślam się, że można je ustawić jako ContainerAware. Oto przykład jak to zrobić

// This is the page.service class 
class MyPageService { 

    public function render(PageTypeInterface $page_type) { 
     $page_type->setContainer($this->container); 

     // do stuff 
    } 
} 

// This is the type strategy 
class MyStrategyType extends ContainerAware implements PageTypeInterface { 
    // you can access the container after MyPageService has injected it. 
} 

Więc w zasadzie każda strategia będzie przedłużyć ContainerAware a page.service by wstrzyknąć kontenera.


EDIT

Jeśli wszystkie strategie są uzależnione od tych samych usług, będę wstrzykiwać je zamiast całego pojemnika.

class MyPageService { 

    public function render(PageTypeInterface $page_type) { 
     $page_type->setService($this->container->get('my_service')); 

     // do stuff 
    } 
} 
+0

To nie jest dobre, aby przekazać pojemnik. Jeśli jego obiekt wymaga doktryny, powinien go wymagać, dodając parametr do konstruktora dla obiektu doktryny. – meze

+0

@meze oczywiście, ale co, jeśli każda strategia ma różne zależności. To byłby jedyny sposób. Jednak osobiście zdefiniowałbym wszystkie strategie jako usługi. – gilden

+0

i jak testowałbyś swoje strategie? użyć ponownie w innym projekcie bez symfony? – meze

3

Usługi są dokładnie tym, czego potrzebujesz. Możliwość wstrzyknięcia zależności dla danej strategii. Następnie wprowadzanie konkretnej strategii do kontrolera (może być również dynamicznym rendererem, który wybiera strategię w czasie wykonywania).

ContainerAware to bardzo zła praktyka, wiąże dany obiekt z wszystkimi usług w kontenerze. Dlatego zdecydowanie zalecałbym unikanie tego.