Monday, June 29, 2009

Implementing Strategies with Enums.

Implementing Strategies with Enums.

As most Design Patterns, Strategy pattern is an incredibly useful pattern to express polimorphic behaviour.
I don't pretend to explain Strategy pattern on this post. My intention is only to show you a nice way of implementing the pattern using a Java Enum.

Sometimes the difference between strategies is small, and you have control over all the strategies. (There is no intention that a client implements its own strategy).
Also, usually each strategy comes in the form of a Singleton instance.
It would be nice to have all Strategies in a common place, sharing a common namespace.

All the previous can be addressed with the use of the Enum construct in Java 1.5+

Let's suppose a Voice "strategizable" class, with two concrete strategies Screaming Voice and Whisper Voice

This is how we would do this with an Enum.

public enum Voice {
SCREAM(){
@Override
public String say(String say){ return say.toUpperCase()+" !!";}
},
WHISPER(){
@Override
public String say(String say){return say.toLowerCase()+ " please ";}
};
public abstract String say(String say);
}

There we have our two Strategy implementations under the same namespace (the ENUM type), singleton guaranteed. To test the startegy we have the following test case.


package misc;

import org.junit.Test;
import static org.junit.Assert.*;

public class VoiceTest {
@Test
public void testVoice() {
// if in good mood
VoiceUser user = new VoiceUser(Voice.WHISPER);

// if in bad mood
VoiceUser user2 = new VoiceUser(Voice.SCREAM);

assertEquals("do that please", user.askSomeone());
assertEquals("DO THAT !!", user2.askSomeone());
}
}

class VoiceUser {
public VoiceUser(Voice voice) {
this.voice = voice;
}

Voice voice;

String askSomeone() {
String string = "Do that";
return voice.say(string);
}
}

No comments: