Skip to main content
Updated date:

Implementing the Strategy Pattern With Java Enums

Author:
implementing-the-strategy-pattern-with-java-enums

This is aimed at beginning, intermediate and self taught programmers who want to know something about the principles behind code they may encounter

The strategy pattern solves the problem of selecting one of a range of possible actions depending on an input datum. It can be regarded as an automaton and can be related to rule based computing frameworks such as Open Rules.

The simplest way to implement the Strategy pattern in Java is probably to use the ENUM class thus decoupling the response from strategy selection.

Rule Based computing

Rule based computing is essentially a set of conditions against which data is tested. For example email filters are human curated rules and some banks allow you to raise your overdraft on line but require you to go to a branch to reduce your overdraft. Some rules may transform the data or infer something from the data, for example in Formal logical languages you may encounter


MALE(X) or FEMALE(X) AND not (ANIMAL(X)) → HUMAN(X)


Data that matches any of rule triggers an action. In most cases it is not necessary to test a datum against all rules. If the data does not match any rules no action is taken.


From the coding perspective, data that does not match the rules must be treated carefully otherwise the program may behave unpredictably (more generally the error handling path within a programme cannot be ignored – this is why the Java SWITCH statement has a default case and data, especially data created by humans, needs continual validation).


You can learn more about rule based systems HERE and the related topic of Logic programming HERE

Enums

An Enum, short for Enumerated Type, is a list of values that function as global constants and can be considered as a list of singleton classes. Enums mayhave different names in different languages (notably Python and R) and be more powerful in some languages than others.

From here on “Enum” will refer to Java Enums.

DISCLAIMER Code here is tutorial code, deliberately incomplete and with no guarantee of correctness especially if ORACLE change their specification. It will be enough to get you started but use at your own risk. America has too many lawyers.

An enum is declared as follows

public enum Something
{
	First {},
	Second{},
	Third{};
}

The curly braces can hold a list of values or a method, which may differ for each constant

Here is an example of including values in the braces

public enum Planet 
{
	 MERCURY("Mercury", "God of thieves");

/* the constructor is mandatory The order of parameters in the constructor defines which value is accessed.
this means MERCURY.name will always be the second number after the {

this constructor will Map 
Mercury.name --> "god of Thieves"
Mercury,attribute -->"Mercury"
Beware of this and include in testing.
*/

Planet(String attribute, String name) 
		{
			this.name = name;
			this.attribute = attribute;
		}

	public String name;
	public String attribute;	 
}	

public static void main(String[] args) 
	{
	System.out.println("Name is " + 	Planet.MERCURY.name);

	}

}

An Enum with Methods for each constant

This Enum delegates greetings to individual nationality classes. This ensures the Enum is minimally coupled to the classes to which it delegates.

Creating a “strategy” box in this way ensures that maintenance is needed only when adding a nationality or an action to the Enum. If you wish you can define an interface the nationality classes must implement.

// you can have more than one method per enum constant but need a corresponding abstract method in the enum body
// it is probably a good idea to delegate as much as possible to reduce the number & complexity of methods per enum constant.
public enum NationalGreetings {
	ENGLISH 
	{ 
		public void greet() { System.out.println(Englishman.greet());}

		public void bye(){System.out.println("Bye");}
		},
	
	FRENCH { 
public void greet()		{ System.out.println(Frenchman.greet());} 

public void bye() {System.out.println("AdIeu");}
					},
	GERMAN { public void greet(){ System.out.println(German.greet());} 
						public void bye() {System.out.println("Auf Wiedersehen");}
					};

	// The abstract methods are required
	public void greet() {};
	public void bye() {};
}

Here is how to call it (when run from command line)

public class Strategies {
	
	public static void main(String[] args) {
 
		for(String argstring : args)
		{

			 stringtoEnumValue(argstring);
		}
	
	}


	private static void stringtoEnumValue(String argstring) {
		try 
			{
				argstring = argstring.toUpperCase(); //simple guard

// The return type for ValueOf() is an Enum constant from NationalGreetings not the Parent Class Enum.
NationalGreetings ng =NationalGreetings.valueOf(argstring);
				ng.greet();
			}
		 catch (Exception ex) 
				{
		 		System.out.println(ex.getMessage());
		 	};
	}
	
	}

Conclusion

The Strategy Pattern can be viewed as a “box” with data dropped in a slot. The box then decides the action performed in response to the data.

Implementing it with Enums lets the enum delegate actions to external classes thus decoupling them from the calling code and reducing the amount of maintenance needed.

Related Articles