使用策略模式的Java Emailer
更新:又增加了一个问题(问题4) 大家好 我正在为自己构建一个自定义电子邮件实用程序。现在,为了遵守单一责任原则,我希望有以下类:MailerSender、MailProvider和EmailObject。MailSender更像是一个委托人,请在下面查看:使用策略模式的Java Emailer,java,oop,design-patterns,strategy-pattern,Java,Oop,Design Patterns,Strategy Pattern,更新:又增加了一个问题(问题4) 大家好 我正在为自己构建一个自定义电子邮件实用程序。现在,为了遵守单一责任原则,我希望有以下类:MailerSender、MailProvider和EmailObject。MailSender更像是一个委托人,请在下面查看: public class MailSender { private IMailProvider mailProvider; public void setMailProvider (IMailProvider provid
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.我是否实施了战略模式?
2.这个设计好吗?邮件提供者知道EmailObject有意义吗?
3.如果我以后有一个需要附件的新EmailObject呢?
4.客户端代码现在需要在创建MailSender之前获取特定的MailProvider。。。这有意义吗?好的,让我们来看看你的问题 1) 模糊地说,是的。你可以说你有“算法”或“策略”,你可以在它们之间选择。然而,我更喜欢将策略模式看作与算法相关的东西。例如,获取搜索结果的不同方法。在这里,您要处理的是不同的代理,您可以将发送电子邮件的角色委托给这些代理。这是一种常见的设计,但我不确定我是否一定会称之为策略。无论哪种方式,设计模式都是为了帮助您思考,而不是将您锁定在特定的名称上 2) 我认为这个设计是合理的。我会使用接口而不是实际的类,尤其是对于EMailObject。此外,应该有一个工厂的电子邮件对象,而不仅仅是新的。很可能每个提供商都会提供自己的“电子邮件对象”,其中包括包的详细信息。您发送的是内容,而不是“信封”
3) 这是使用接口而不是类的另一个很好的理由。您可能希望包含元数据和潜在附件的getter/setter,因为它们是您域(电子邮件)的合法部分。我认为这里最重要的问题是:
MailSender sender = new MailSender(new FakeMailProvider());
sender.send(new EmailObject());
SMTPMailProvider provider = new SMTPMailProvider();
provider.send(new EmailObject());
编辑:第四季度。在发送EmailObject之前,客户端需要将特定的MailProvider传递给MailSender。这句话可以转化为这样的话:“客户要求电子邮件服务发送电子邮件,传递电子邮件数据并选择传输方式(发送电子邮件的一种方式)”。我认为这是可以的,但是如果您不想每次都指定传输,您可以将其更改为“…服务然后使用配置的传输发送电子邮件”,并将提供程序实例化移动到配置中 对于这句话+1:“无论哪种方式,设计模式都是为了帮助你思考,而不是把你锁定在一个特定的名字上。”我花了一段时间才明白:^)我正在试图找到一个好方法来做到这一点。MailerSender是一个EmailObject接口,而不是一个具体的类,提供者如何“获取”信息?接口将为具体类中的信息提供一个契约,但是当我使用添加的信息创建一个新对象时会发生什么呢?在基本电子邮件(收件人、发件人、抄送、主题、正文)与带有附件(字节[]数据)的电子邮件的情况下,您必须确定每个提供商都熟悉的电子邮件内容,并在界面中提供获取者。提供商通常只能处理电子邮件,因此您需要在电子邮件中输入您需要的所有内容。@bedwyr:谢谢。每当我被要求背诵GOF的书时,我仍然试图在求职面试中传达这一信息。EMailObject工厂会是什么样子?为什么我需要它?为什么客户端不能只编写一个“新”的代码,并使用变体来填充对象?您认为客户端必须将邮件提供者传递给邮件发送者有意义吗?有没有办法使用工厂或构建器模式来解决这个问题?恭喜你,你刚刚意识到需要依赖注入!别以为我是在开你的玩笑,这真的像是程序员的下一关:@bbmud酷!但是如果没有DI/IoC框架,您将如何处理这个问题呢?在MailSender类上定义第二个空构造函数,它使用MailProvider的默认版本的新实例(所谓的poor's man依赖项注入)调用第一个构造函数。