Strategy

Strategy е представител на поведенческите шаблони. Използва се когато даден проблем може да бъде разрешен по различни начини и избора за неговото решение се взема по време на изпълнението.

За имплементация на Strategy е необходимо:

  • интерфейс Strategy;
  • конкретни имплементации на интерфейса - за всяка отделна стратегия;
  • контекстен обект с поведение, което зависи от избраната стратегия.

Подобна имплементация прави промяната на дадена стратегия или добавянето на нова безпроблемно, без това да налага промени в контекстния обект и в клиентската част, която използва този контекстен обект. Освен това стратегиите са взаимозаменяеми.

Като недостатък на Strategy може да се посочи необходимостта клиента да е запознат с различните стратегии, за да може да ги прилага правилно. Освен това подобен подход не е много ефективен в практиката ако имаме само две или три стратегии.

Като пример по-долу е показана програма, която изчислява лице на геометрична фигура.

public interface ShapeStrategy {

    double calculateArea();
}

Необходими са конкретни имплементации:

public class RectangleShape implements ShapeStrategy{

    private int length;
    private int width;

    public RectangleShape(int length, int width) {
        this.length = length;
        this.width = width;
    }

    @Override
    public double calculateArea() {
        return length * width;
    }
}
public class TriangleStrategy implements ShapeStrategy{

    private int a;
    private int b;
    private int c;

    public TriangleStrategy(int a, int b, int c) {
        if ((a + b > c) && (a + c > b) && (b + c > a)) {
            this.a = a;
            this.b = b;
            this.c = c;
        }
    }

    @Override
    public double calculateArea() {
        int p = (a + b + c)/2;
        return Math.sqrt(p * (p - a) * (p - b) * (p - c));
    }
}
public class CircleStrategy implements ShapeStrategy{

    private int radius;

    public CircleStrategy(int radius) {
        this.radius = radius;
    }

    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

След това трябва да бъде създаден и контекстен клас:

public class Shape {

    private ShapeStrategy shapeStrategy;

    public Shape(ShapeStrategy shapeStrategy) {
        this.shapeStrategy = shapeStrategy;
    }

    public double getArea() {
        return shapeStrategy.calculateArea();
    }
}

Клиентският код изглежда по следния начин:

public class Application {

    public static void main(String[] args) {
        Shape circle = new Shape(new CircleStrategy(2));
        System.out.println("Circle's area is: " + String.format("%.2f", circle.getArea()));

        Shape triangle = new Shape(new TriangleStrategy(5, 4, 6));
        System.out.println("Triangle's area is: " + String.format("%.2f", triangle.getArea()));

        Shape rectangle = new Shape(new RectangleShape(4, 7));
        System.out.println("Rectangle's area is: " + rectangle.getArea());
    }
}