2

I need to process notification messages that gets pushed to my application. where the messages contain notification types like catalog_purchased, catalog_expired, catalog_denied etc. and In future new set of notification types would be added as well. What would be a good Design Pattern (and any Java 8 features) to process all these messages based on Notification types instead of just using if-else blocks?

public class CustomMessage(){
  private String messageType;
  private Message message;
}
public void pushedMessage(CustomMessage message){
   //*TO-DO* need to implement code that handles one message at a time
} 
dreambigcoder
  • 1,859
  • 4
  • 22
  • 32
  • EventBus of some kind. Guava provides a nice one – Eugene Jul 31 '19 at 01:02
  • @Eugene Do you think EventBus is needed if I had to process just one message at a time? – dreambigcoder Jul 31 '19 at 02:31
  • why not say that in the question and not the comments? This changes that problem quite a lot, since now you need a queue... But IIRC guava's EventBus will process elements sequentially anyway. – Eugene Jul 31 '19 at 10:22
  • I modified my question, I already have a queue. I'm only trying to decouple the message processing logic. – dreambigcoder Jul 31 '19 at 13:51

2 Answers2

1

In my opinion best design pattern is Factory pattern. since client doesn't know which service or method would be call based on data entry. I just provided a sample although you can use java 8 features. there is a good sample.

so first of all define an interface:

public interface MessageProcess {

  public void pushedMessage(CustomMessage message); 

  public String messageType();

}

and suppose you would have some process service like these:

public class ServiceA implements MessageProcess{

  @Override
  public void pushedMessage(CustomMessage message) {

  }

  @Override
  public String messageType() {
      return "messageType1";
  }
}

and also:

public class ServiceB implements MessageProcess {

  @Override
  public void pushedMessage(CustomMessage message) {
      System.out.println("pushed message by serviceB: " + message.toString());
  }

  @Override
  public String messageType() {
      return "messageType2";
  }
}

now you can create a Factory class which identify specify service based on message type.

public class MessageFactory {

  public MessageProcess getByType(String messageType) {
     if (messageType.equals("messageType1"))
         return new ServiceA();
     else if (messageType.equals("messageType2"))
         return new ServiceB();
     return null;
  }
}

and now we use it such as this:

 public class MessageProcessTest {
  public static void main(String[] args) {
     MessageFactory messageFactory = new MessageFactory();

      messageFactory.getByType("messageType2").pushedMessage(new CustomMessage("catalog1"));
  }
}
Hadi J
  • 16,989
  • 4
  • 36
  • 62
0

You can create a map with message type as key and processing logic as value

public static Map<String, Processor> PROCESSORS_MAP = Map.of(
    "catalog_purchased", customMsg -> System.out.println("catalog_purchased: " + customMsg),
    "catalog_expired", customMsg -> System.out.println("catalog_expired: " + customMsg),
    "catalog_denied", customMsg -> System.out.println("catalog_denied: " + customMsg)
);

where Processor is a functional interface

@FunctionalInterface
interface Processor {
    void process(CustomMessage msg);
}

and use it as follows

PROCESSORS_MAP.get(customMessage.getMessageType()).process(customMessage);

Of course if logic for processing a message is pretty big you should create a class that implements Processor instead of using lambda.

Adrian
  • 2,984
  • 15
  • 27
  • Yes, the logic would be big to process the message, I figured I could just use different methods with same arguments rather than classes. Is there any name for this kind of pattern? – dreambigcoder Jul 31 '19 at 20:25
  • 1
    @dreambigcoder I don't think that's a pattern, more like procedural programming with lots of if. If your concern is too much code in lambda then you can create implementations `Map.of( "catalog_purchased", new CatalogPurchasedProcessor());` and it's easier to UT this way, also you can mark these as Spring beans and use DI – Adrian Aug 01 '19 at 06:11