Strategia jest czynnościowym wzorcem obiektowym. Wzorzec składa się z wielu związanych ze sobą algorytmów ukrytych wewnątrz klasy sterującej zwanej Context. Program klienta może wybrać jeden z tych algorytmów lub najodpowiedniejszy z nich. Intencją wzorca jest wymienność algorytmów w trakcie działania programu oraz ich hermetyzacja. Bardzo łatwo dodaje się nowe algorytmy, poprzez utworzenie nowej klasy implementującej dany interfejs. Conext może w danej chwili mieć wybraną tylko jedną strategię.
Kiedy to może mieć zastosowanie:
- naliczanie podatku w sklepie zależnie od kraju zamieszkania kupującego,
- Kompresowanie plików z wykorzystaniem różnych algorymtów,
- Zapisywanie plików w różnych formatach.
Przykład:
Codziennie jeżdżę do pracy samochodem, jednak w sobotę w ramach mojego udziału dla ochronoy środowiska naturalnego – samochód zostawiam w garażu i jadę metrem ( :D ). W niedzielę dla poprawienia kondycji poruszam sie tylko rowerem. Nie zmienia to faktu, że każdego dnia gdzieś się przemieszczam za pomocą środka transportu. Stwórzmy interfejs dla niego.
1 2 3 4 |
public interface SrodekTransprotu { public void jedz(); } |
Jest to interfejs dla wszystkich naszych strategii: Metro, Rower i Samochód:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
public class Samochod implements SrodekTransprotu { public void jedz() { przekrecKluczyk(); doDechy(); } private void doDechy() { System.out.println("Wrrrrrrrrrrrrrrrrrrrrrr......"); } private void przekrecKluczyk() { System.out.println("Brum...brum... brum..."); } } public class Rower implements SrodekTransprotu { public void jedz() { wsiadzNaSiodelko(); pedaluj(); } private void pedaluj() { System.out.println("No to kręcimy pedałkami..."); } private void wsiadzNaSiodelko() { System.out.println("Wsiadam na siodełko..."); } } public class Metro implements SrodekTransprotu { public void jedz() { kupBilet(); wsiadajIJedz(); } private void wsiadajIJedz() { System.out.println("Szzzzzzz..... "); } private void kupBilet() { System.out.println("Ulgowy poproszę..."); } } |
Strategie mamy napisane więc czas na Context – w naszym przypadku klasa Podróznik:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public class Podroznik { private SrodekTransprotu srodekTransprotu; public Podroznik() { GregorianCalendar gc = new GregorianCalendar(); switch (gc.get(Calendar.DAY_OF_WEEK)) { case Calendar.SUNDAY: { srodekTransprotu = new Rower();//niedziela, więc rower break; } case Calendar.SATURDAY: { srodekTransprotu = new Metro(); //w sobotę Metro break; } default: { srodekTransprotu = new Samochod();//a resztę życia w samochodzie } } srodekTransprotu.jedz(); } public static void main(String[] args) { Podroznik podroznik = new Podroznik(); } } |
W naszym Contex’cie wybór strategii zależny jest od dnia tygodnia, ale nic nie stoi na przeszkodzie aby zastosować inny algorytm.
Bardzo często wzorzec Strategia można spotkać w połączeniu z jednym z wzorców fabrykujących, które zastępują Context.
Diagram wzorca strategia: