Java Design Patterns – Implementation of Strategy Design Pattern

design-patternsjava

Here is my code:

public class StrategyDemo {

        public static void main(String[] args) {

            Phone ipPhone = new IPPhone("1234", "ProviderA");
            Phone tdmPhone = new TDMPhone("4567", "ProviderB");

            ipPhone.getRecordingResource();
            tdmPhone.getRecordingResource();

            ipPhone.setRecordingResource(Resource.IPRecorderIP2);       
            ipPhone.getRecordingResource();

        }

    }

enter image description here

As I understood, a strategy pattern made that I would be able to change dynamically objects.

I always have hard time to actuality think of something to implement to practice on them.

This implementation is actually a strategy implementation ? How should I improve it?


Regarding comments asking to clarify my needs, I will try to explain the problem that I created that it will be more clear to determine if I used strategy correctly.

A phone should have an ability to be recorded.

A phone can be one of 2 types – IPPhone or TDMPhone.
A recording resource can be one of 2 types – TDMRecorder or IPRecorder.

IPRecorder should but not must to record an IPPhone.
TDMRecorder should but not must to record an TDMPhone.

An actual recorder is a host in that case that is represented with an IP.

I was trying to implement it that way, that I would be able to change dynamically during runtime the resource the a phone is been recorded on (an IP address).

As I understood the part that is missing for me is to have under Record class an abstract method startRecording and the ability to change the recording resource from IPRecorder to an TDMRecorder and vice versa?

Is the problem that I defined suitable for a strategy design pattern?

Best Answer

You're question is a bit unclear, but I'll explain what the Strategy pattern is in case you don't have a good understanding.

Strategy allows you to swap part of the functionality of an object dynamically during runtime. This is done by encapsulating the different functionalities in classes that all share a common supertype, and having the object in question (the 'context') own a reference of this supertype.

Than, when the object wants to perform some functionality, it actually delegates to the Strategy object it owns. We can swap the current Strategy object for a different one dynamically via e.g. a public setter method. Thus swapping the functionality owned by the object.

Note that the Strategy pattern is called that because it allows you to choose different 'strategies' for performing generally the same operation.

For example, in a game you might have a Soldier class. Objects of this class are able to attack bad guys via their attack() method.

But what if you wanted attack() to do something different based on the current weapon the soldier holds? For example if currently the weapon is a gun, attack() will shoot bullets. If it's a knife, attack() will make the soldier stab people.

A naive way to approach this, would be for Soldier to hold a String variable that signifies what the current weapon is. attack() will than have a long else if chain to determine the correct logic according to the current weapon. Something like this:

class Soldier{
    String weapon;
    void setWeapon(String w){ weapon = w; }
    void attack(){
        if(weapon.equals("gun")) // shoot bullets
        else if(weapon.equals("knife")) // slash people
        // else if ...
    }
}

But this approach is bad and definitely not very Object Oriented. What's so bad about it?

Well, suppose you already had 5 different kinds of weapons, and wanted to add another one to the game. You'd have to go into Soldier and add another else if to match.

That's not so bad, but what if more classes in your game needed to use weapons? For example, a DefenseTurret could also hold a specific kind of weapon that would govern the way it attack()s.

That would mean a lot of code duplication between Soldier and DefenseTurret. And again, if you want to add a new weapon - you need to go to both these classes and add logic to them, resulting in classes that keep growing and more and more code duplication. Probably resulting in nasty bugs.

The Strategy pattern is there exactly to provide a more elegant and OO solution to these situations.

With Strategy, each kind of weapon will be implemented in it's own Weapon subclass. Weapon would be an abstract class (or interface) that defines an abstract attack() method. Each of it's subclasses implements this method differently.

Soldier, instead of holding a String weapon member, will have a Weapon weapon member. And it's attack() method, instead of containing a long else if chain, will simply delegate to the weapon: weapon.attack(). Code to clarify:

class Soldier{
    // .. stuff omitted
    Weapon weapon;
    void attack(){
        weapon.attack();
    }
    void setWeapon(Weapon newWeapon){
        weapon = newWeapon;
    }
}
abstract class Weapon{
    public abstract void attack();
}
class Gun extends Weapon{
    public void attack{ /* shoot some bullets */ }
}
class Knife extends Weapon{
    public void attack{ /* stab some bad guys */ }
}

Much more elegant.

Here's a UML diagram to clarify even more:

enter image description here

And now, what if you wanted to give DefenseTurret some gun shooting capabilities? Just give it a Weapon reference and have it delegate to it, like you did with Soldier. You can reuse the code you already wrote without copy-pasting it all the time.


I hope this clarifies what Strategy is. Regarding your question, I couldn't really understand it, but it seems to me what you're doing doesn't clarify as a Strategy implementation since your swapping data (i.e. with a simple setter that sets a String value), but not swapping functionality and logic.

I'll be happy to help if you explain more clearly what your problem is.