0

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?

  • Since this regards specific code rather than a general question about Strategy, would this question be better asked in codereview.stackexchange.com ? – Rob Aug 1 '14 at 17:09
  • @RobY I think this question is highly conceptual. – Tulains Córdova Aug 1 '14 at 18:55
  • 3
    @RobY - CR.SE doesn't allow for design reviews. Programmers allows for design reviews, but this one is too broad at the moment. If the scope was narrowed to focus on a specific aspect of the design (or pattern) then it would likely be on-topic for Programmers. I'm voting to put on hold as too broad so the OP has a chance to update the question. I'll vote to reopen once the scope is narrowed. – GlenH7 Aug 1 '14 at 18:57
  • The idea behind this question was just to get a fill of the strategy design pattern. This is my first time implementing it , just want to make sure that i use it the right way. – USer22999299 Aug 1 '14 at 19:14
  • 1
    I did edit the question to be more specific, defined a problem above. – USer22999299 Aug 2 '14 at 8:36
3

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.

  • Hm... ok so in my case , you think that it would be more convenience that a IPPhone will be able dynamically change his resource to a TDMRecorder rather then changing the Host from IPRecorder1 to IPRecorder2 ? (design wise) , cus right now i don't change the functionality , just the resource , the functionality stay the same. – USer22999299 Aug 1 '14 at 19:17
  • 1
    @USer22999299 I don't understand what your problem is. I'll be glad to help if you clarify what you need and what your dillema is. Anyway, I added a lot of explanation to the question as to what Strategy is, if it helps. – Aviv Cohn Aug 1 '14 at 22:33
  • 1
    +1 Other reasons the non-OO (if/else) solution can be bad is that each condition, if it's complex, might require using other objects, thereby creating coupling between Soldier and those other objects. The Strategy approach encapsulates that coupling into the Weapon object. Soldier has less responsibilities (higher cohesion) and is simpler. Also, you're using your improperly as well as it's its sometimes. – Fuhrmanator Aug 2 '14 at 1:00
  • Thank you very much , the explanation with the soldiers and the weapons was very clear. That's the thing , always with simple example it seems reasonable , but when facing a problem it is hard for me to understand how to use it. I will try to re define my problem on my post. Thank you. – USer22999299 Aug 2 '14 at 7:00
  • @USer22999299 Sure. Keep in mind that design patterns are simply 'documented solutions' with names. They help you communicate ideas with other programmers and they also might teach you stuff. But don't try to force a pattern where it doesn't belong just because it's a pattern, it'll just make your designs more messy. – Aviv Cohn Aug 2 '14 at 9:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.