Strategy Pattern

The Strategy Pattern faces one issue we have with polymporphism in a modern OO language like Java. Making changes in an existing structure of objects with an inheritance tree or adding a new object to this strucute is hard and can take a long time.

Let me give you an example.

We´re having a superclass hero. A hero is able to attack some one else or defend his self.

package com.herostrategy.entity;
/**
 *
 * @author javadevcorner.com
 */
public abstract class Hero {

    public void attack() {
        //some logic in here
    }
    public void defend() {
       //some logic in here
    }
}

But not every hero has the same way and strength to attack someone else or defend him self.
So everytime we create a new hero, you either have to override the methods (in case hero is abstract) or you have to use the “mother-method” cause of inheritance.
Both are not really good approaches if you don´t want to write redundant (or nearly redundant) code all the time.
That´s exactly what the Strategy Pattern is going to “fix”.
In this pattern you design a behaviour for attack (and defend) and some concrete implementations.

Implementation

So let´s start with our Strategy-Interface for the attack-behaviour.

Attack behaviours

At first we create an interface which defines our attack method. You can look at it as a contract for our attack method.

package com.herostrategy.attackStrategy;
/**
 *
 * @author javadevcorner.com
 */
public interface AttackInterface {
    
    public void attack();
} 

After we´ve finished with this we´re going to create some concrecte implementations of our attack interface.

AngryAttack

package com.herostrategy.attackStrategy;
/**
 *
 * @author javadevcorner.com
 */
public class AngryAttack implements AttackInterface{

    @Override
    public void attack() {
        System.out.println("aaaaangry Attack !");
    }
}

DirectAttack

package com.herostrategy.attackStrategy;
/**
 *
 * @author javadevcorner.com
 */
public class DirectAttack implements AttackInterface{

    @Override
    public void attack() {
        System.out.println("DIRECT ATTACK WOHA !!");
    }
}

SneakyAttack

package com.herostrategy.attackStrategy;
/**
 *
 * @author javadevcorner.com
 */
public class SneakyAttack implements AttackInterface{

    @Override
    public void attack() {
        System.out.println("sneaky from behind attack");
    }
}

As you can see, every “attack-type” has a different implementation of our attack method.

Heroes and their attacks

Now we create some heroes. For explanation I´m just creating one hero. Feel free to do some more.

Hero modification

package com.herostrategy.entity;

import com.herostrategy.attackStrategy.AngryAttack;
import com.herostrategy.attackStrategy.AttackInterface;
/**
 *
 * @author javadevcorner.com
 */
public abstract class Hero {

    //Default behaviour
    AttackInterface attack = new AngryAttack();
    
    public void attack() {
        attack.attack();
    }
    public void defend() {
    }
}

Hero is going to get a little bit more fancy. First of all we define a default behaviour for every new hero that will be derived from the superclass.
After that, we use the instance varible in our hero attack method and call the strategy interfaces attack method.

Batman

Batman is a hero, who loves the night and always works from behind. Just when he needs to, he is directly attacking some. Here is his implementation

package com.herostrategy.entity;

import com.herostrategy.attackStrategy.AttackInterface;
import com.herostrategy.attackStrategy.SneakyAttack;
/**
 *
 * @author javadevcorner.com
 */
public class Batman extends Hero{
    
    private AttackInterface attack = new SneakyAttack();

    @Override
    public void attack() {
        attack.attack();
    }
    
    public void setAttack(AttackInterface attack) {
        this.attack = attack;
    }
}

We extend Hero and override the attack() method of the superclass.
The default behaviour of Batman is a sneaky attack, so we override the default behaviour too (instance variable).

Execute

public static void main(String[] args) {
    
    Batman batman = new Batman();
    batman.attack();
    batman.setAttack(new DirectAttack());
    batman.attack();
}

As I said, batman is starting his fight with a sneaky attack. After all the enemies have seen him, he starts with his direct attacks.

You output should be like this:

sneaky from behind attack
DIRECT ATTACK WOHA !!

 

Now before you stop, try to implement the defend() method. It will be a good practice for you.

 

So thanks for reading and have fun with the Strategy Pattern

Feel free to share