Электронная почта в Java с использованием шаблона стратегии - PullRequest
6 голосов
/ 18 мая 2009

ОБНОВЛЕНО: Добавлен еще один вопрос (Вопрос № 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. Теперь клиентскому коду необходимо получить определенный MailProvider перед созданием MailSender ... имеет ли это смысл?

Ответы [ 2 ]

7 голосов
/ 18 мая 2009

Хорошо, давайте рассмотрим ваши вопросы.

1) Смутно, да. Вы можете утверждать, что у вас есть «алгоритмы» или «стратегии» и вы можете выбирать между ними. Однако я предпочитаю думать о шаблоне стратегии как о чем-то, что имеет отношение к алгоритмам. Например, разные способы получить результат поиска. Здесь вы имеете дело с различными агентами, которым вы делегируете роль отправки электронной почты. Это общий дизайн, но я не уверен, что обязательно назвал бы это стратегией. В любом случае, шаблоны проектирования предназначены для того, чтобы помочь вам думать, а не привязывать вас к конкретному имени.

2) Я думаю, что дизайн разумный. Я бы использовал интерфейсы, а не реальные классы, особенно для EMailObject. Кроме того, должна быть фабрика для объектов электронной почты, а не просто новые. Также очень вероятно, что каждый провайдер предоставит свой собственный «объект электронной почты», который включает в себя детали пакета. Вы отправляете содержимое, а не «конверт».

3) Это еще одна веская причина использовать интерфейсы, а не класс. Возможно, вы захотите включить методы получения / установки метаданных и, возможно, вложения, поскольку они являются законной частью вашего домена (электронной почты).

0 голосов
/ 18 мая 2009

Наиболее важные вопросы здесь, на мой взгляд:

  1. Можете ли вы проверить свой компонент без отправки реальных писем? Да:

    MailSender sender = new MailSender(new FakeMailProvider());
    sender.send(new EmailObject());
    
  2. Можете ли вы проверить свои почтовые провайдеры без остальной части приложения? Да:

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

Вы успешно отсоединили поставщиков от отправителей.

РЕДАКТИРОВАТЬ: Q4. Клиент должен передать определенный MailProvider MailSender перед отправкой EmailObject. Это утверждение может быть преобразовано во что-то вроде этого: «клиент просит почтовую службу отправлять электронную почту, передавая данные электронной почты и выбирая транспорт (способ отправить электронную почту)». Я думаю, что все в порядке, но если вы не хотите каждый раз указывать транспорт, вы можете изменить его на «... служба затем отправляет электронную почту с использованием настроенного транспорта» и перенести создание провайдера в конфигурацию.

...