FatimahFatCakes
FatimahFatCakes

Reputation: 331

Pattern for switch cases

I have a series of switch cases, but it seems a bit too complicated. What is the best way to simplify it? I was thinking of using the strategy design pattern.

My initial thoughts were to make sendReport into a single method, with the method calling sendReport from each of the different classes. However, I am not sure how to implement this. Would anyone give me some guidance, and maybe some suggestions on what I could do to make this switch cases simpler.

Thank you.

public static boolean sendReport(AuthToken token, Student client, List<ContactMethod> bestOptions, String data) {
    for (ContactMethod method : bestOptions) {
        switch (method) {
            case TEXT:
                String textMessage = client.getPhoneNumber();
                if (null != textMessage) {
                    TEXT.sendReport(token, client.getFName(), client.getLName(), data, textMessage);
                    return true;
                }
                break;
            case POST:
                String address = client.getAddress();
                String suburb = client.getSuburb();
                String state = client.getState();
                String postcode = client.getPostCode();
                if (null != address && null != suburb &&
                    null != state && null != postcode) {
                    Mail.sendReport(token, client.getFName(), client.getLName(), data, address, suburb, state, postcode);
                    return true;
                }
                break;
            case ELECTRONICMAIL:
                String email = client.getEmailAddress();
                if (null != email) {
                    Email.sendReport(token, client.getFName(), client.getLName(), data, email);
                    return true;
                }
                break;
            case VOICECALL:
                String number = client.getPhoneNumber();
                if (null != number) {
                    PhoneCall.sendReport(token, client.getFName(), client.getLName(), data, number);
                    return true;
                }
                break;
            case FACE_TO_FACE:
                String face2face = client.getFace2Face();
                String personName = client.getPersonName();
                if (null != face2face && null != personName) {
                    Face_To_Face.sendReport(token, client.getFName(), client.getLName(), data, face2face,personName);
                    return true;
                }
                break;
            case MAGIC:
                String magicID = client.getMagic();
                if (null != magicID) {
                    magic.sendReport(token, client.getFName(), client.getLName(), data, magicID);
                    return true;
                }
                break;
            default:
                return false;
        }
    }
    return false;
}

Upvotes: 0

Views: 889

Answers (4)

tquadrat
tquadrat

Reputation: 4034

Yes, an implementation of the Strategy/Policy pattern would do the job. And basically, two out of the three already existing answers show a possible implementation for that pattern (Michael's answer and Ali Gelenler's answer), although Michael does not think that his implementation would follow a pattern …

If the set of possible contact methods is fixed, you can even add sendReport() as a method to the enum, with different implementations for each enum instance. This spares you a dedicated registry for the strategies (and you do not need to define several different classes).

The cleaner path would be (as suggested by the already mentioned answers) to define an interface ContactMethod and to implement that for each method of contact you need. It has the advantage that you can easily add additional contact methods (in particular if you utilise the java.util.ServiceLoader API).

The disadvantage is that, if the contact method is an attribute of an externalised entity, you need some kind of a registry for the strategies and a mapping from the name of the strategies to their implementations – as said, something you get for free, when you extend (abuse?) the enums.

Upvotes: 1

Ali Gelenler
Ali Gelenler

Reputation: 241

Define a common interface ContactMethod having a sendReport method and create different implementation classes for each switch case that implement the ContactMethod. For example;

public static boolean sendReport(AuthToken token, Student client, List<ContactMethod> bestOptions, String data) {
   for (ContactMethod method : bestOptions) {
      if (method.sendReport(token, client, data))
         return true;
   }
}

public class TextContactMethod implements ContactMethod {
    public boolean sendReport(AuthToken token, Student client, String data) {
            String textMessage = client.getPhoneNumber();
            if (null != textMessage) {
                TEXT.sendReport(token, client.getFName(), client.getLName(), data, textMessage);
                return true;
            }
       return false;
    }
}

Upvotes: 1

Stephen C
Stephen C

Reputation: 718758

I would simply make the switch "blocks" into methods and call them; e.g.

public static boolean sendReport(AuthToken token, Student client, 
                                 List<ContactMethod> bestOptions,
                                 String data) {
    for (ContactMethod method : bestOptions) {
        boolean res;
        switch (method) {
            case TEXT:
                res = processText(token, client, data);
                break;
            case POST:
                res = processPost(token, client, data);
                break;
            ...
            default:
                res = false;
        }
        if (res) {
            return true;
        }
    }
    return false;
}

private boolean processText(AuthToken token, Student client) {
    String textMessage = client.getPhoneNumber();
    if (null != textMessage) {
        TEXT.sendReport(token, client.getFName(), client.getLName(), 
                        data, textMessage);
        return true;
    } else {
        return false;
    }
}

Sure, you could dress that up with a design pattern, but simple procedural abstraction works just as well.

Upvotes: 2

Michael
Michael

Reputation: 44110

You don't even need a design pattern, you just need basic polymorphism.

Change ContactMethod from an enum to an interface. Each case statement becomes an implementation of the interface

public class TextContactMethod implements ContactMethod { ... }    

sendReport becomes

for (ContactMethod method : bestOptions) {
    method.fooBar(token, client);
}

Upvotes: 2

Related Questions