Java中的电子邮件使用策略模式

时间:2009-05-17 23:05:43

标签: java oop design-patterns strategy-pattern

更新:又增加了一个问题(问题#4)。

大家好,

我正在构建一个自定义电子邮件实用程序。现在,为了遵守单一责任原则,我想拥有以下类: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是一个包含相关电子邮件信息的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.我是否实施了战略模式?
   这个设计好吗? MailProvider是否有意识到EmailObject?    3.如果我以后有新的EmailObject需要附件怎么办?    4.客户端代码现在需要在创建MailSender之前获取特定的MailProvider ...这有意义吗?

2 个答案:

答案 0 :(得分:7)

好的,让我们回答您的问题。

1)含糊不清,是的。你可以说你有“算法”或“策略”,你可以在它们之间进行选择。但是,我更倾向于将策略模式视为与算法相关的事物。例如,获取搜索结果的方法不同。在这里,您要处理您委派发送电子邮件角色的不同代理。这是一种常见的设计,但我不确定我是否一定称之为策略。无论哪种方式,设计模式都可以帮助您思考,而不是锁定您的特定名称。

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

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

答案 1 :(得分:0)

我认为最重要的问题是:

  1. 您是否可以在不发送实际电子邮件的情况下测试您的组件?是:

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

    SMTPMailProvider provider = new SMTPMailProvider();
    provider.send(new EmailObject());
    
  3. 您已成功地将提供者与发件人分离。

    编辑:Q4。客户端需要在发送EmailObject之前将特定的MailProvider传递给MailSender。此声明可以转换为类似的内容:“客户端要求电子邮件服务发送电子邮件,传递电子邮件数据和选择传输(发送电子邮件的方式)”。我认为没关系,但是如果您不想每次都指定传输,您可以将其更改为“...服务然后使用配置的传输发送电子邮件”并将提供程序实例化移动到配置。