更新:又增加了一个问题(问题#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 ...这有意义吗?
答案 0 :(得分:7)
好的,让我们回答您的问题。
1)含糊不清,是的。你可以说你有“算法”或“策略”,你可以在它们之间进行选择。但是,我更倾向于将策略模式视为与算法相关的事物。例如,获取搜索结果的方法不同。在这里,您要处理您委派发送电子邮件角色的不同代理。这是一种常见的设计,但我不确定我是否一定称之为策略。无论哪种方式,设计模式都可以帮助您思考,而不是锁定您的特定名称。
2)我认为设计合理。我会使用接口而不是实际的类,尤其是对于EMailObject。此外,应该有一个电子邮件对象的工厂,不要只是新的。每个提供商也很可能会提供自己的“电子邮件对象”,其中包括包详细信息。您正在发送内容,而不是“信封”。
3)这是使用接口而不是类的另一个好理由。并且您可能希望包含元数据和可能附件的getter / setter,因为它们是您域中的合法部分(电子邮件)。
答案 1 :(得分:0)
我认为最重要的问题是:
您是否可以在不发送实际电子邮件的情况下测试您的组件?是:
MailSender sender = new MailSender(new FakeMailProvider());
sender.send(new EmailObject());
您可以在没有其他应用程序的情况下测试您的电子邮件提供商吗?是:
SMTPMailProvider provider = new SMTPMailProvider();
provider.send(new EmailObject());
您已成功地将提供者与发件人分离。
编辑:Q4。客户端需要在发送EmailObject之前将特定的MailProvider传递给MailSender。此声明可以转换为类似的内容:“客户端要求电子邮件服务发送电子邮件,传递电子邮件数据和选择传输(发送电子邮件的方式)”。我认为没关系,但是如果您不想每次都指定传输,您可以将其更改为“...服务然后使用配置的传输发送电子邮件”并将提供程序实例化移动到配置。