[Design Pattern](EN) Strategy Pattern Concept and Example

Post about Strategy Pattern.


Environment and Prerequisite

  • Java


What is Strategy Pattern?

Strategy Pattern

  • Strategy Pattern: It is a design pattern which define set of algorithms and interchange those algorithms when it is needed. Those algorithms are encapsulated by class. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use.
  • In case of java, define strategy to interface and implement it in class to encapsulate it. Add it to object’s method when you use it. There will be an examples below.
  • Image Source: https://en.wikipedia.org/wiki/Strategy_pattern


Necessity

Robot Example

  • Let’s imagine we make robots. Robots will be TaekwonV, Atom and Gundam. How to implement them then? Make basic form in abstract Robot class and use inheritance(‘extends’ keyword in java).
  • First, let’s make abstract Robot class, TaekwonV class and Atom class.


Example

Robot

public abstract class Robot {
    private String name;
    public Robot(String name){ this.name = name; }

    public String getName(){ return name;}

    public abstract void attack();
    public abstract void move();
}

TaekwonV

public class TaekwonV extends Robot {

    public TaekwonV(String name){
        super(name);
    }

    @Override
    public void attack() {
        System.out.println("kick");
    }

    @Override
    public void move() {
        System.out.println("walk");
    }
}

Atom

public class Atom extends Robot {

    public Atom (String name){
        super(name);
    }

    @Override
    public void attack() {
        System.out.println("punch");
    }

    @Override
    public void move() {
        System.out.println("fly");
    }
}

Main

public class Main {
    public static void main(String[] args) {

        Robot taekwonV = new TaekwonV("TaekwonV");
        Robot atom = new Atom("Atom");

        System.out.println("I am " + taekwonV.getName());
        taekwonV.attack();
        taekwonV.move();

        System.out.println();

        System.out.println("I am " + atom.getName());
        atom.attack();
        atom.move();
    }
}


Problems in above code.

  • To modify existed code to new code, we need to modify existed code and it violates OCP(Open-Closed Principle). For example in above code if we like to use same move() method in both Atom and TaekwonV we need to modify existed code and it also cause duplicate code. As the number of robots grows, it is hard to manage code.
  • What if we like to make new robot and use same method of TaekwonV’s move() and Atom’s attack()? There will be a code duplication if we copy and paste it.


Solution

  • In implementing robot, we need to find which part of code are changeable. Find changing part, encapsulate it and make it interchangeable.
  • In above code, attack() and move() are changeable. So encapsulate those methods and use it when it is needed. It prevents from code duplication and code modifying.
  • Make each to java’s interface and make object when it is needed.
  • In case of move() method, make MovingStrategy interface and implements it in class.


Example

Robot

public abstract class Robot {
    private String name;
    private AttackStrategy attackStrategy;
    private MovingStrategy movingStrategy;

    public Robot(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void attack() {
        attackStrategy.attack();
    }

    public void move() {
        movingStrategy.move();
    }

    public void setAttackStrategy(AttackStrategy attackStrategy) {
        this.attackStrategy = attackStrategy;
    }

    public void setMovingStrategy(MovingStrategy movingStrategy) {
        this.movingStrategy = movingStrategy;
    }

}

AttackStrategy

public interface AttackStrategy {
    public void attack();
}

MovingStrategy

public interface MovingStrategy {
    public void move();
}

KickingStrategy

public class KickingStrategy implements AttackStrategy {
    @Override
    public void attack() {
        System.out.println("kick");
    }
}

PunchingStrategy

public class PunchingStrategy implements AttackStrategy {
    @Override
    public void attack() {
        System.out.println("punch");
    }
}

WalkingStrategy

public class WalkingStrategy implements MovingStrategy {
    @Override
    public void move() {
        System.out.println("walk");
    }
}

FlyingStrategy

public class FlyingStrategy implements MovingStrategy {
    @Override
    public void move() {
        System.out.println("fly");
    }
}

TaekwonV

public class TaekwonV extends Robot {
    public TaekwonV(String name) {
        super(name);
    }
}

Atom

public class Atom extends Robot {
    public Atom(String name) {
        super(name);
    }
}

Gundam

public class Gundam extends Robot {
    public Gundam(String name) {
        super(name);
    }
}

Main

public class Main {
    public static void main(String[] args) {

        Robot taekwonV = new TaekwonV("TaekwonV");
        Robot atom = new Atom("Atom");
        Robot gundam = new Gundam("Gundam");

        taekwonV.setAttackStrategy(new KickingStrategy());
        taekwonV.setMovingStrategy(new WalkingStrategy());

        atom.setAttackStrategy(new PunchingStrategy());
        atom.setMovingStrategy(new FlyingStrategy());

        gundam.setAttackStrategy(new PunchingStrategy());
        gundam.setMovingStrategy(new WalkingStrategy());

        System.out.println("I am " + taekwonV.getName());
        taekwonV.attack();
        taekwonV.move();

        System.out.println();

        System.out.println("I am " + atom.getName());
        atom.attack();
        atom.move();

        System.out.println();

        System.out.println("I am " + gundam.getName());
        gundam.attack();
        gundam.move();

    }
}


Reference