Quickly learning the Strategy Design Pattern with Java

Post to Twitter

Using Java I’ll quickly walk through how you can use the Strategy Design Pattern. We will cover how one might approach a particular problem and solve it, then we will re-examine the problem and apply a better solution using the strategy pattern. I’m not going to get bogged down though on the whole “is-a” and “has-a” relationships but instead focus purely on one possible was to code this and before you know it you’ll have used the strategy pattern.

Lets say your in the military and are charged with defending a country. A top general tells you that you need to design a computer system that will activate the military when an invasion happens. You might begin to layout your code like this:

public abstract class Military
{
	public void defend()
	{
		System.out.println("The military is defending!");
	}
}
public class Army extends Military
{
}
public class Defender
{
	public static void main(String[] args)
	{
		Army army = new Army();
		army.defend();
	}
}

This works pretty well to begin with. Assuming the enemy always invades via land since the Army is primarily land based. What happens when the enemy is doing an airborne assault or coming from the sea? It would be handy to have the Air Force take out the enemy airborne aircraft and the Navy to take out the enemy ships before they hit your shores. Your design is modified like so:

For the Army:

public class Army extends Military
{
	public void defend()
	{
		System.out.println("The Army is defending on land!");
	}
}

For the Navy:

public class Navy extends Military
{
	public void defend()
	{
		System.out.println("The Navy is defending on the high seas!");
	}
}
public class AirForce extends Military
{
	public void defend()
	{
		System.out.println("The Air Force is defending the skies!");
	}
}

You implement this as such:

public class Defender
{
	public static void main(String[] args)
	{
		Army army = new Army();
		army.defend();

		Navy navy = new Navy();
		navy.defend();

		AirForce airForce = new AirForce();
		airForce.defend();
	}
}

You see the following results:

The Army is defending on land!
The Navy is defending the high seas!
The Air Force is defending the skies!

Problem solved huh? Not quite… You are quickly reminded by a Navy Admiral that the Navy is also responsible for defending under the water was well as the surface. The Air Force General tells you that they are also responsible for defending threats in outer space. You could modify your code like this for the Navy to start with:

public class Navy extends Military
{
	public void defend()
	{
		System.out.println("The Navy surface fleet is defending the high seas!");
		System.out.println("The Navy submarines are defending under high seas!");
	}
}

The problem is you need to make changes to all the classes to clearly define who defends what, etc. not to mention there might be new branches of the military created as technology changes, etc. The Navy always has at least one ship on the ocean but perhaps the submarine fleet is docked and not always defending since this is a poor country and only has perhaps one submarine. You should maybe use the Strategy Design Pattern to save yourself additional future work and additional maintenance, etc. Lets redesign this!

First we know that each branch of the military for your country has a primary function, to “defend”. Lets take that and move this into it’s own interface like so:

public interface Defend
{
	public void defend();
}

Lets make sure each branch has their primary objective clearly defined (ie: The Air Force primarily will have threats in the skies right now, not space).

Lets add a few classes to handle defending:

public class DefendOnTheOcean implements Defend
{
	@Override
	public void defend()
	{
		System.out.println("We are defending the high seas!");
	}
}
public class DefendUnderTheOcean implements Defend
{
	@Override
	public void defend()
	{
		System.out.println("We are defending under the high seas!");
	}
}
public class DefendTheLand implements Defend
{
	@Override
	public void defend()
	{
		System.out.println("We are defending the land!");
	}
}
public class DefendTheSkies implements Defend
{
	@Override
	public void defend()
	{
		System.out.println("We are defending the skies!");
	}
}
public class DefendSpace implements Defend
{
	@Override
	public void defend()
	{
		System.out.println("We are defending space!");
	}
}

Modify the Military class:

public abstract class Military
{
	private Defend defend;

	public void setTheDefender(Defend defend)
	{
		this.defend = defend;
	}

	public void defend()
	{
		this.defend.defend();
	}
}

Now modify the Army, Air Force and Navy classes:

// Army
public class Army extends Military
{
	public Army()
	{
		setTheDefender(new DefendTheLand());
	}
}


// Navy
public class Navy extends Military
{
	public Navy()
	{
		setTheDefender(new DefendOnTheOcean());
	}
}

// Air Force
public class AirForce extends Military
{
	public AirForce()
	{
		setTheDefender(new DefendTheSkies());
	}
}

Test out the new structure:

public class Defender
{
	public static void main(String[] args)
	{
		Army army = new Army();
		army.defend();

		Navy navy = new Navy();
		navy.defend();
		navy.setTheDefender(new DefendUnderTheOcean());
		navy.defend();

		AirForce airForce = new AirForce();
		airForce.defend();
	}
}

The out output is:

We are defending the land!
We are defending the high seas!
We are defending under the high seas!
We are defending the skies!

Now if the Air Force gets a threat from space we can do this:

public class Defender
{
	public static void main(String[] args)
	{
		AirForce airForce = new AirForce();
		airForce.setTheDefender(new DefendSpace());
		airForce.defend();
	}
}

We see this:

We are defending space!

Lets say now I create a new branch of the military that has responsibilities that can be in the skies, land, or the 4th dimension (their primary domain). We can do this:

public class Defender
{
	public static void main(String[] args)
	{
		UberElite uberElite = new UberElite();
		uberElite.defend();
		uberElite.setTheDefender(new DefendSpace());
		uberElite.defend();
	}
}

Result:

We are defending the 4th dimension!
We are defending space!

My naming convention could’ve been better but hopefully you get the general idea.

For more reference and the “theory” of it all check out the Wikipedia article.

Post to Twitter

This entry was posted in Design Patterns, Java. Bookmark the permalink.

4 Responses to Quickly learning the Strategy Design Pattern with Java

  1. Diaa Kasem says:

    Strategy pattern is awesome for saving common strategies to assign later on to other components. I use lots of patterns in my current project.

    But, I found it will be an improvement for that pattern to use Java Enum instead of classes to define strategies. I hope you can correct me if I’m wrong.

    With enumeration, one can easily know where all the strategies exist, use switch if he needed to.

    Thank you for this post.

  2. Aishwarya Sirohi says:

    Great article! Simple and to the point. Thanks!

    I see you have articles on Decorator and Adapter as well. May I request for articles on the other commonly used patterns. Would be really helpful.

  3. mohamed omar says:

    great job

  4. Thasha says:

    great article, thanks a lot.

Comments are closed.