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();
}
}