Best practices for implementing Factory pattern using Symfony2

I make a messenger that can send emails or sms messages and have the ability to send them now or send them later (information is stored in the database). I made 2 decisions, but none of them satisfy me.

I centralize the code in one Factory, and the code for the Factory template is very simple:

class MessageFactory { static public function get($type,$em) { $instance = null; switch ($type) { case 'email': $instance = new EmailMessage($em); break; .... return $instance; } class EmailMessage implements MessangerInterface { ... public function send( $eMessage,array $receivers, $time=NULL) { interface MessangerInterface { public function send($message,array $receivers); } 

1st solution: Just call the regular static method

 $messanger = Factory\MessageFactory::get('email',$em); $messanger->send($eMessage, array('tom'=>' tom@gmail.com ')); 

This is a bad decision, because I need to pass to Doctrine Manager as a parameter to the method

2nd solution: To use it as a Symfony 2 service

 services: my.messanger: class: Bundle\Factory\MessangerInterface factory_class: Bundle\Factory\MessageFactory factory_method: get arguments: messanger_type: %messanger.type% 

and pass the Doctrine as an argument. But using this solution, I can not select messager.type in my code, it was determined using the configuration parameter as email or sms ; I need to be able to select a type in the code.

I also have a problem that inside the class I need to send email or SMS, which means that I need an external service, getting it like this:

 class EmailMessage implements MessangerInterface { if ('AppCache' == get_class($kernel)) { $kernel = $kernel->getKernel(); } $kernel->getContainer()->get('mailer')->send($eMessage); 

which seems like a very bad practice.

Please can you advise me any better solutions?

I want to follow the concept of a โ€œthin model of a thick controllerโ€.

+5
source share
1 answer

It seems that option 2 using Symfony 2 Services would be better.

I assumed that you let Factory be a Service and pass a type to get an instance of Messenger, not to fix it in config, but if you want to have only one of each type of Messenger then it is useless (Factory will create more and more messengers). So instead, I think you need to define two services, one for each messenger.

And if you do not want to receive another service in your Messenger, you need to enter it when you receive Messenger.

eg.

 services: mailer: class: Mailer smser: class: SMSer email.messanger: class: Bundle\Factory\MessangerInterface factory_class: Bundle\Factory\MessageFactory factory_method: get arguments: messanger_type: email sender: @mailer sms.messanger: class: Bundle\Factory\MessangerInterface factory_class: Bundle\Factory\MessageFactory factory_method: get arguments: messanger_type: sms sender: @smser 

And your Factory should accept the new $ sender argument:

 class MessageFactory { static public function get($type,$em,$sender) { $instance = null; switch ($type) { case 'email': $instance = new EmailMessage($em, $sender); break; .... return $instance; } interface MessangerInterface { public function send($message,$sender, array $receivers); } 

Then, when you call him, you ask any of the messengers to do this:

 $this->get('email.messenger')->send($emailMessage); $this->get('sms.messenger')->send($smsMessage); 
+6
source

Source: https://habr.com/ru/post/1203695/


All Articles