Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emailer in Java using Strategy Pattern

UPDATED: Added one more question (Question #4).

Hi all,

I'm building myself a custom emailing utility. Now, to obey Single Responsibility Principle, I want to have the following classes: MailerSender, MailProvider and EmailObject. The MailSender is more of a delegate, check it out below:

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
        }
    }
}

The MailSender requires an IMailProvider email provider that does the work of sending the email. Find it below:

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
    }
}

I have defined a few strategies above, but it can be extended to any number. Since the MailSender can change it's provider at any time, it effectively implements the strategy pattern right?

The EmailObject is a POJO containing relavent email information:

public class EmailObject {
    private String to;
    private String from;
    private String cc;
    private String subject;
    private String body;

    // setters and getters for all
}

Client code will then look like:

MailSender sender = new MailSender(new SMTPMailProvider());
sender.send(new EmailObject());
sender.setMailProvider(new JMSMailProvider());
sender.send(new EmailObject());

My questions are:

1. Have I implemented the Strategy Pattern?
2. Is this design good? Does it make sense for a MailProvider to be aware of an EmailObject?
3. What if I had a new EmailObject later on that required an attachment?
4. The client code now needs to acquire a specific MailProvider before creating a MailSender ... does this make sense?

like image 875
djunforgetable Avatar asked May 17 '09 23:05

djunforgetable


People also ask

What is strategy pattern in Java with example?

Strategy design pattern is one of the behavioral design pattern. Strategy pattern is used when we have multiple algorithm for a specific task and client decides the actual implementation to be used at runtime.

What is the use of a strategy pattern give an example where it can be used?

A good example of strategy pattern would be in a game where we can have different characters and each character can have multiple weapons to attack but at a time can use only one weapon.

Which is the most used design pattern in Java?

The Singleton Design Pattern is a Creational pattern, whose objective is to create only one instance of a class and to provide only one global access point to that object. One commonly used example of such a class in Java is Calendar, where you cannot make an instance of that class.


1 Answers

Ok, let's go through your questions.

1) Vaguely, yes. You could argue that you have "algorithms" or "strategies" and that you can pick between them. However, I prefer to think of the strategy pattern as something that is relevant to algorithms. For example, different ways to get a search result. Here you are dealing with different agents to which you delegate the role of sending email. That's a common design, but I am not sure I would necessarily call it strategy. Either way, design patterns are meant to help you think, not to lock you to a specific name.

2) I think the design is reasonable. I would use interfaces rather than actual classes, especially for the EMailObject. In addition, there should be a factory for email object, don't just new them. It is also very likely that each provider will provide it's own "email object" that includes package detail. You are sending the contents, not the "envelope".

3) That's another good reason to use interfaces rather than a class. And you may want to include getters/setters for metadata and potentially attachments because they are a legitimate part of your domain (an email).

like image 199
Uri Avatar answered Sep 22 '22 13:09

Uri