6

更新:又增加了一个问题(问题#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. 我是否实施了策略模式?
2、这个设计好不好?MailProvider 知道 EmailObject 是否有意义?
3. 如果我以后有一个新的 EmailObject 需要附件怎么办?
4. 客户端代码现在需要在创建 MailSender 之前获取特定的 MailProvider ......这有意义吗?

4

2 回答 2

7

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

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

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

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

于 2009-05-17T23:13:15.417 回答
0

在我看来,这里最重要的问题是:

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

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

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

您已成功地将提供者与发送者分离。

编辑:第四季度。客户端在发送EmailObject之前需要将具体的MailProvider传递给MailSender。该语句可以转换成这样的形式:“客户要求电子邮件服务发送电子邮件、传递电子邮件数据并选择传输方式(一种发送电子邮件的方式)”。我认为没关系,但是如果您不想每次都指定传输,您可以将其更改为“......然后服务使用配置的传输发送电子邮件”并将提供程序实例化移动到配置中。

于 2009-05-18T00:18:57.007 回答