Factory Method and Strategy Design Patterns with Java

The problem: If we don’t know what Design Patterns we have available to solve day-to-day situations, it’s going to be very difficult to implement the best solutions.

Our code can have very high coupling and no cohesion which causes no flexibility and no scalability. Then, you know who is going to appear. If you thought bugs, yes! You are right! The bugs will have a party in the code, making our lives very stressful.

Very experienced programmers of GOF (Gang of Four) Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides created Design Patterns, and solutions for common and day-to-day coding situations. Many of the problems GOF faced were solved after creating the Patterns, that’s why it’s so important to know them.

Instead of going through the same problems they did for many years, we can learn those Patterns and make our code clean and flexible.

I had the following situation at my job. I had to receive a command from a Web Service and call the specific Service for each command.

What solution would be appropriate for this situation?

Factory Method + Strategy

The diagram:

class_diagram.PNG

Get the source code to follow the article:
https://github.com/rafadelnero/design-patterns-saga

1 – Invoker class: the executeAction() method will receive the command and depending on the command received, it will invoke the correspondent Service.

public class BillingInvoker {

  public void executeAction(String command) {
    int idContract = 1;
    new BillingServiceFactory(command).getService().execute(idContract);
  }
}

2 – This is where we use the pattern Factory Method. Pretty simple, isn’t it? We receive the command in the constructor and decide what Service we are going to invoke.

I created an Enum to make the selection clearer and easier to read. I just make a parse to an Enum. Then I choose the Service to be invoked in the command ‘switch case’.

Another important thing to be aware of is that the method getService() is returning an interface. I am using polymorphism in this method. It returns any BillingService, any class that implements it.

public class BillingServiceFactory {

  private String command;

  public BillingServiceFactory(String command) {
    this.command = command;
  }

  public BillingService getService() {
    BillingEnum billingEnum = BillingEnum.parse(command);

    switch (billingEnum) {

      case PRE_CALCULATION:
        return new BillingPreCalculation();

      case CALCULATION:
        return new BillingCalculation();

      default:
        throw new IllegalArgumentException("The service does not exist.");
    }
  }

}

3 – Let’s check out the BillingService interface. Actually, it’s very simple, but necessary to make the Strategy pattern work. With this interface, we can use the very powerful technique, polymorphism. We can invoke the execute(long idContract) method from any class that implements BillingService.

public interface BillingService {

public void execute(long idContract);

}

4 – Now that we know about the BillingService interface, we can come back to the Invoker class and check it out better. No secret, we just:

  1. Instantiated the class BillingServiceFactory
  2. Passed the command in the constructor
  3. Invoked the getService() method where we get one implementation of the interface BillingService

Here is the magic! We are going to invoke the execute(long idContract) method from the interface, and guess what, we are controlling what implementation we are invoking by the command!

We are isolating the responsibilities and making the code powerful! An important detail is that we must create a generic method name in BillingService, because we don’t know what we are going to invoke. When we return the implementation of the interface we can only use the interface method. You could use a specific method from the implementation if you use class cast only.

public class BillingInvoker {

  public void executeAction(String command) {
    int idContract = 1;

    new BillingServiceFactory(command).getService().execute(idContract);
  }

}

5 – The invocation! Let’s suppose we receive a command to invoke BillingCalculation. What are we going to do? We are going to invoke the BillingCalculation method!

public class BillingCalculation implements BillingService {

  public void execute(long idContract) {
    calculateContract(idContract);
  }

  public void calculateContract(long idContract) {
    System.out.println("BillingCalculation was invoked");
  }
}

6 – The output! It will be printed: BillingCalculation was invoked

We made it!

Summary of our actions:

  1. The Invoker class instantiates the Factory class
  2. The Factory class decides what Service is going to be invoked
  3. The Invoker gets the Service
  4. The Invoker invokes the method of the Service implementation
  5. The output of the Service implementation is printed

You can test the pattern with these Unitary Tests:

public class StrategyFactoryMethodTest {

  private static final long idContract = 1;

  @Test
  public void invokePreCalculationTest() {
    BillingService billingService = new BillingServiceFactory
             (BillingEnum.PRE_CALCULATION.getCode()).getService();

    billingService.execute(idContract);
    Assert.assertTrue(billingService instanceof BillingPreCalculation);
  }

  @Test
  public void invokeCalculationTest() {
    BillingService billingService = new BillingServiceFactory
            (BillingEnum.CALCULATION.getCode()).getService();

    billingService.execute(idContract);
    Assert.assertTrue(billingService instanceof BillingCalculation);
  }

  @Test(expected = IllegalArgumentException.class)
    public void notExistentCommandTest() {
    new BillingServiceFactory("777").getService();
  }
}

To practice using this Pattern you can implement a new unitary test to a new Service and make it work!

Written by
Rafael del Nero
Join the discussion

14 comments