Strategia

Strategia

Wzorzec Strategia (ang. Strategy) jest wzorcem projektowym, który umożliwia definiowanie rodzin algorytmów, umieszczanie ich w oddzielnych klasach, a następnie używanie ich wymiennie. Dzięki temu możemy dynamicznie zmieniać zachowanie obiektu w trakcie działania programu, bez konieczności modyfikowania jego kodu.

Kluczowe aspekty wzorca Strategia:

  • Definiowanie rodziny algorytmów: Każdy algorytm jest reprezentowany przez osobną klasę, która implementuje wspólny interfejs.
  • Wymienność algorytmów: Algorytmy mogą być zamieniane w trakcie działania programu.
  • Zasada Open/Closed: Możemy łatwo dodawać nowe algorytmy, bez modyfikacji istniejących klas.

Kiedy używać wzorca Strategia?

  • Gdy mamy różne warianty algorytmów, które mogą być dynamicznie zmieniane.
  • Gdy chcemy oddzielić logikę algorytmu od kodu klienta, aby móc dodawać nowe algorytmy bez zmian w istniejącym kodzie.
  • Gdy potrzebujemy elastyczności w wyborze algorytmów podczas działania programu.

Przykład bez wzorca Strategia

Załóżmy, że mamy system, który wykonuje operacje matematyczne. Zamiast strategii, mamy jeden duży warunkowy blok, który określa, którą operację wykonać:

class Calculator {
    public int calculate(String operation, int a, int b) {
        switch (operation) {
            case "add":
                return a + b;
            case "subtract":
                return a - b;
            case "multiply":
                return a * b;
            case "divide":
                return b != 0 ? a / b : 0;  // Zakładamy, że nie dzielimy przez 0
            default:
                throw new IllegalArgumentException("Nieznana operacja");
        }
    }
}

// Klient
public class Main {
    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        
        int result1 = calculator.calculate("add", 10, 5);
        System.out.println("Dodawanie: " + result1);
        
        int result2 = calculator.calculate("subtract", 10, 5);
        System.out.println("Odejmowanie: " + result2);
    }
}

Problemy z takim podejściem:

  • Brak rozszerzalności: Każdorazowo, gdy chcemy dodać nową operację, musimy modyfikować kod w klasie Calculator.
  • Złożoność warunków: Jeśli operacji będzie więcej, kod stanie się bardziej skomplikowany i trudniejszy do utrzymania.

Przykład z użyciem wzorca Strategia

Teraz zmienimy podejście na takie, które stosuje wzorzec Strategia, co pozwoli nam łatwo dodawać nowe algorytmy i dynamicznie je zmieniać.

1 Interfejs strategii

// Interfejs Strategii
interface OperationStrategy {
    int doOperation(int a, int b);
}

2. Implementacje strategii (algorytmy)

// Konkretna strategia - dodawanie
class AdditionStrategy implements OperationStrategy {
    @Override
    public int doOperation(int a, int b) {
        return a + b;
    }
}

// Konkretna strategia - odejmowanie
class SubtractionStrategy implements OperationStrategy {
    @Override
    public int doOperation(int a, int b) {
        return a - b;
    }
}

3. Klasa kontekstowa

class Calculator {
    // Wykonanie operacji na podstawie dostarczonej strategii
    public int executeStrategy(OperationStrategy strategy, int a, int b) {
        return strategy.doOperation(a, b);
    }
}

4. Klient (główna część programu)

public class Main {
    public static void main(String[] args) {
        Calculator calculator = new Calculator();

        // Dodawanie
        int result1 = calculator.executeStrategy(new AdditionStrategy(), 10, 5);
        System.out.println("Dodawanie: " + result1);

        // Odejmowanie
        int result2 = calculator.executeStrategy(new SubtractionStrategy(), 10, 5);
        System.out.println("Odejmowanie: " + result2);
    }
}

Zalety wzorca Strategia:

  • Rozszerzalność: Możemy łatwo dodawać nowe algorytmy (np. nowe operacje matematyczne) poprzez dodanie nowych klas implementujących interfejs OperationStrategy, bez modyfikacji istniejących klas.
  • Elastyczność: Możemy dynamicznie zmieniać strategię w czasie działania programu.
  • Rozdzielenie odpowiedzialności: Każda operacja (algorytm) jest wydzielona w osobnej klasie, co upraszcza kod i sprawia, że jest bardziej przejrzysty.
Scroll to Top