2009-05-17 84 views
6

已更新:增加了一个问题(问题#4)。Java中使用策略模式的Emailer

大家好,

我正在建立一个自定义的电子邮件实用程序。现在,要遵守单一责任原则,我想要有以下类:MailerSender,MailProvider和EmailObject。该MailSender更多的是代表的,检查出来如下:

public class MailSender { 
    private IMailProvider mailProvider; 

    public void setMailProvider (IMailProvider provider) { 
     this.mailProvider = provider; 
    } 

    // option to set it up during construction 
    public MailSender (IMailProvider provider) { 
     this.mailProvider = provider; 
    } 

    public void sendEmail(EmailObject obj) { 
     if(mailProvider == null) 
      throw new RuntimeException("Need a mail provider to send email."); 

     try { 
      mailProvider.send(obj); 
     } catch (Exception e) { 
      // do something here 
     } 
    } 
} 

的MailSender需要IMailProvider电子邮件提供商,做发送电子邮件的工作。找到它如下:

public interface IMailProvider { 
    public void sendEmail(EmailObject obj); 
} 

public class SMTPEmailProvider implements IMailProvider { 
    public void sendEmail(EmailObject obj) { 
     // use SMTP to send email using passed-in config 
    } 
} 

public class JMSEmailProvider implements IMailProvider { 
    public void sendEmail(EmailObject obj) { 
     // push emails to JMS queue to be picked up by another thread 
    } 
} 

我已经定义了上面的几个策略,但它可以扩展到任何数量。由于MailSender可以随时更改它的提供者,它有效地实现了策略模式的权利?

的EmailObject是包含relavent电子邮件信息的POJO:然后

public class EmailObject { 
    private String to; 
    private String from; 
    private String cc; 
    private String subject; 
    private String body; 

    // setters and getters for all 
} 

客户端代码如下:

MailSender sender = new MailSender(new SMTPMailProvider()); 
sender.send(new EmailObject()); 
sender.setMailProvider(new JMSMailProvider()); 
sender.send(new EmailObject()); 

我的问题是:

1.让我实现了策略模式?
2.这个设计好吗? MailProvider知道EmailObject是否合理?
3.如果以后有新的EmailObject需要附件,该怎么办?
4.客户端代码现在需要在创建MailSender之前获取特定的MailProvider ......这是否有意义?

回答

7

好的,让我们来看看你的问题。

1)不太确定,是的。你可以争辩说,你有“算法”或“策略”,你可以选择它们。但是,我更愿意将策略模式视为与算法相关的内容。例如,获取搜索结果的不同方法。在这里,您正在处理您委派发送电子邮件角色的不同代理。这是一个常见的设计,但我不确定我是否会将其称为策略。无论哪种方式,设计模式都是为了帮助您思考,而不是锁定您的具体名称。

2)我认为设计是合理的。我会使用接口而不是实际的类,特别是对于EMailObject。另外,应该有一个电子邮件对象的工厂,不要只是新的电子邮件对象。每个提供商很可能会提供包含包详细信息的自己的“电子邮件对象”。你正在发送的内容,而不是“信封”。

3)这是使用接口而不是类的另一个很好的理由。而且您可能希望包含元数据和潜在附件的getter/setter,因为它们是您域(电子邮件)的合法部分。

+3

+1对于本声明:“无论哪种方式,设计模式都是为了帮助您思考,而不是锁定您的具体名称。”我花了一段时间才知道:^) – bedwyr 2009-05-18 00:51:27

+0

我试图找出一个很好的方法来做到这一点。 MailerSender获得一个EmailObject接口而不是一个具体的类,提供者如何“获取”信息?该接口将为具体类中的信息提供合约,但是当我使用_added_信息创建新对象时会发生什么? 对于基本电子邮件(来自cc,subject,body)与带有附件(byte [] data)的电子邮件的情况? – djunforgetable 2009-05-18 01:28:52

0

最重要的问题,以下是我的观点:

  1. 你能不发送电子邮件的实际测试你的组件?是:

    MailSender sender = new MailSender(new FakeMailProvider()); 
    sender.send(new EmailObject()); 
    
  2. 您可以在没有其他应用程序的情况下测试您的电子邮件提供商吗?是:

    SMTPMailProvider provider = new SMTPMailProvider(); 
    provider.send(new EmailObject()); 
    

您已成功从发件人脱钩提供商。

编辑:Q4。客户端在发送EmailObject之前需要将特定的MailProvider传递给MailSender。这个陈述可以转换成这样的东西:“客户要求电子邮件服务发送电子邮件,传送电子邮件数据和选择传输(发送电子邮件的一种方式)”。我认为它是可以的,但是如果你不想每次都指定传输,你可以将它改为“...服务然后使用配置的传输发送电子邮件”并将提供者实例化移动到配置。