使用Symfony2实现Factory模式的最佳实践

Vla*_*ape 7 factory-pattern symfony

我正在制作一个可以发送电子邮件或短信的信使,并且可以立即发送或稍后发送(信息保存在数据库中).我已经做了两个解决方案,但两个都不令我满意.

我正在将代码集中在一个Factory中,而Factory模式的代码非常简单:

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);
}
Run Code Online (Sandbox Code Playgroud)

第一个解决方案:只需调用普通的静态方法

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

这是一个糟糕的解决方案,因为我需要将Doctrine Manager作为参数传递给方法

第二种解决方案:将其用作Symfony 2服务

services:
my.messanger:
    class: Bundle\Factory\MessangerInterface
    factory_class: Bundle\Factory\MessageFactory
    factory_method: get
    arguments:
        messanger_type: %messanger.type%
Run Code Online (Sandbox Code Playgroud)

并且还将学说作为论据传递.但是使用这样的解决方案我不能在我的代码中选择messanger.type,它使用配置参数定义为emailsms; 我需要在代码中具有选择类型的能力.

另外我有一个问题,我需要在课堂上发送电子邮件或短信,这意味着我需要一个外部服务,得到这样的:

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

这似乎是非常糟糕的做法.

拜托,您能告诉我任何更好的解决方案吗?

我想遵循"瘦控制器脂肪模型"的概念.

fru*_*ous 6

似乎选项2,使用Symfony 2服务,将是最好的.

我考虑建议您让Factory成为服务,并传递类型以获取Messenger实例,而不是将其修复为配置,但如果您想要的只是每种类型的Messenger中的一种,那么这是无益的(工厂将继续创造越来越多的信使.所以我认为你需要定义两个服务,每个Messenger一个.

如果您不想在Messenger中获取另一个服务,则需要在获取Messenger时注入该服务.

例如

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
Run Code Online (Sandbox Code Playgroud)

你的工厂需要接受新的$ sender参数:

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);
}
Run Code Online (Sandbox Code Playgroud)

然后,当你打电话给它时,你要求任何一个信使:

$this->get('email.messenger')->send($emailMessage);
$this->get('sms.messenger')->send($smsMessage);
Run Code Online (Sandbox Code Playgroud)