Wzorzec Strategia jako jeden z wzorców behawioralnych pozwala definiować różne algorytmy lub zachowania (np. sposób sortowania, obliczania rabatu) i wybierać je w czasie działania programu, przekazując je jako obiekty. Dzięki temu łatwo możemy podmienić „strategię” bez zmiany kodu głównej klasy.
Typowy przykład: System płatności, gdzie możesz przekazywać różne sposoby płatności (np. karta, PayPal, przelew) jako strategię.
Zastosowanie i charakterystyka
Wzorzec projektowy Strategia (Strategy) pozwala na wydzielenie zestawu algorytmów lub zachowań do osobnych klas i dynamiczne wybieranie jednego z nich w trakcie działania programu. Głównym celem jest ułatwienie rozbudowy oraz testowania kodu poprzez uniezależnienie obiektu kontekstu od szczegółów implementacyjnych strategii.
- Strategia to wzorzec behawioralny, który polega na delegowaniu określonego zachowania do obiektu pośredniego („strategii”) zgodnie z ustalonym interfejsem.
- Najczęściej stosowany, gdy chcemy dynamicznie zmieniać algorytm wykonujący określoną funkcjonalność, zachowując spójność interfejsu komunikacji z kontekstem.
- W PHP coraz popularniejszym substytutem dla strategii są funkcje anonimowe, ale wzorzec nadal pozostaje czytelny w bardziej złożonych przypadkach.
Przykład implementacji strategii w PHP
Przykład 1: Rabaty w sklepie internetowym
interface DiscountStrategy {
public function calculate(float $amount): float;
}
class FixedDiscount implements DiscountStrategy {
public function calculate(float $amount): float {
return $amount - 10;
}
}
class PercentageDiscount implements DiscountStrategy {
public function calculate(float $amount): float {
return $amount * 0.8;
}
}
class Order {
private DiscountStrategy $discountStrategy;
private float $amount;
public function __construct(float $amount, DiscountStrategy $discountStrategy) {
$this->amount = $amount;
$this->discountStrategy = $discountStrategy;
}
public function getTotal(): float {
return $this->discountStrategy->calculate($this->amount);
}
}
// Użycie
$order = new Order(100, new FixedDiscount());
echo $order->getTotal(); // 90
$order = new Order(100, new PercentageDiscount());
echo $order->getTotal(); // 80
W powyższym przykładzie możemy łatwo podmieniać strategię naliczania rabatu bez modyfikowania klasy Order
Przykład 2: Transport na lotnisko
interface TransportStrategy {
public function transport(User $user): TransportResult;
}
class CityBusTransport implements TransportStrategy {
public function transport(User $user): TransportResult {
// Transport busem
return new TransportResult();
}
}
class PersonalCarTransport implements TransportStrategy {
public function transport(User $user): TransportResult {
// Transport prywatnym autem
return new TransportResult();
}
}
class TransportationToAirport {
private TransportStrategy $strategy;
public function __construct(TransportStrategy $strategy) {
$this->strategy = $strategy;
}
public function run(User $user): TransportResult {
return $this->strategy->transport($user);
}
}
Możesz dynamicznie przypisywać różne strategie transportu, co ułatwia rozbudowę i testowanie systemu.
Gdzie najczęściej stosować?
- Konkretne algorytmy, które mogą się różnić (sortowanie, rabaty, płatności)
- Różne sposoby realizacji podobnego zadania (kompresja, generowanie ID, logika płatnicza)
Wzorzec Strategia jest prosty, przejrzysty i wyjątkowo przydatny przy rozbudowanych, testowalnych systemach, które muszą być gotowe na częste zmiany algorytmów
