Skip to main content

wzorzec strategia:

Wzorzec strategia należy do grupy wzorców behawioralnych, czyli dotyczy algorytmów i rozdzielania odpowiedzialności miedzy różnymi obiektami. Wzorzec ten pozwala zdefiniować całą rodzinę algorytmów, umieścić je w osobnych klasach i spowodować, że obiekty tych klas będą wymienialne. Pozwala to na dynamiczne korzystanie z algorytmu, który jest w danej chwili potrzebny. Natomiast klasa kliencka nie ma pojęcia, który algorytm jest wykorzystywany.
Zastosowanie wzorca:

  • gdy chcemy użyć różnych wariantów jednego algorytmu w obrębie obiektu i tym samym dokonywać wyboru wariantu w trakcie działania programu
  • gdy mamy wiele podobnych klas które różnią się sposobem wykonywania operacji
  • gdy chcemy odizolować logikę biznesową klasy od implementacji algorytmów (bo nie są istotne w kontekście tej logiki)
  • gdy chcemy odizolować logikę biznesową klasy od implementacji algorytmów (bo nie są istotne w kontekście tej logiki)gdy klasa zawiera duży operator warunkowy, który decyduje o wyborze wariantu algorytmu

Zatem naszym zadaniem będzie napisać program który poinformuje na jaką imprezę możemy się zdecydować w zależności od budżetu. Dla ułatwienia wyświetlimy tylko informacje na jaką imprezę możemy sobie pozwolić z naszym obecnym budżetem. Do dzieła!
W pierwszej kolejności pokaże kod który nie wykorzystuje wzorca strategia. Oto i on:

public class BirthdayPartyMain {
    public static void main(String[] args){
        int budget = 1100;
        typeOfEvent(budget);
    }
    public static void typeOfEvent(int budget){
        if(budget>0&&budget<300){
            System.out.println("Plener!");
        }else if(budget>=300&&budget<800){
            System.out.println("Niespodzianka!");
        }else if(budget>=800){
            System.out.println("Bar!");
        }else { System.out.println("Nie stać nas na imprezę! Musimy zrobić zrzutkę..."); }
    }
}

Jak widać nie jest on dość skomplikowany, ale wyobraź sobie, że mogą dojść nam nowe mozliwosci np. Impreza w wynajętym lokalu itp. Mogą również nastąpić jakieś nowe warunki, które trzeba by było spełnić: czas realizacji, liczba gości, dodatkowe atrakcje itp. Wówczas nasza instrukcja warunkowa mogłaby urosnąć do sporych rozmiarów. Zmiany mogłyby być dla nas sporym utrudnieniem. Nie wspomnę już, że w przykładzie tylko wyświetlamy na ekran typ imprezy na którą możemy sobie pozwolić. A co by było gdyby trzeba wywołać jakieś dodatkowe operacje.

Teraz czas by zająć się tym samym problemem, ale z użyciem ww. wzorca. Zobaczmy jak mógłby wyglądać diagram klas:

design patterns strategy

Widzimy, że mamy klasę abstrakcyjną Party i rozszerzającą ją klasę Birthday w której zapadnie decyzja której strategii użyjemy w zależności od budżetu. To ona będzie komunikowała się z obiektem strategii za pośrednictwem interfejsu. Jest również wspomniany interfejs dzięki któremu uruchamiamy dana strategię – jest ich cztery. Poniżej umieściłam kod dla poszczególnych klas.

public abstract class Party {
    PartyInterface partyInterface;
    public double budget;

    public void createParty(){
        setInterface();
        partyInterface.createParty();
    }
    public void setInterface()
    {
        this.partyInterface = typeOfEvent();
    }
    public abstract PartyInterface typeOfEvent();
}
public class Birthday extends Party {
    public Birthday(double budget){
        this.budget =budget;
    }
    public PartyInterface typeOfEvent(){
        if(budget >0&& budget<300) return new PartyOutdoors();
        else if(budget >=300&& budget <800) return new PartySurprise();
        else if(budget >=800) return new PartyInClub();
        else return new NoParty();
    }
}
public interface PartyInterface {
    public void createParty();
}
public class NoParty implements PartyInterface {
    @Override
    public void createParty() {
        System.out.println("Nie stać Cię na organizacje imprezy!");
    }
}
public class PartyInClub implements PartyInterface {
    @Override
    public void createParty() {
        System.out.println("W klubie");
    }
}
public class PartyOutdoors implements PartyInterface {
    @Override
    public void createParty() {
        System.out.println("W plenerze");
    }
}
public class PartySurprise implements PartyInterface {
    @Override
    public void createParty() {
        System.out.println("Niespodzianka!");
    }
}

Klasa main oraz rezultat wywołania:

import java.awt.image.ImagingOpException;
import java.util.InputMismatchException;
import java.util.Scanner;

public class PartyMain {
    public static void main(String[] args) {
        //strategy
        menu();
        boolean flag = true;
        while (flag) {
            Scanner scan = new Scanner(System.in);
            int opcja = scan.nextInt();
            switch (opcja) {
                case 1: {
                    System.out.println("Podaj budżet: ");
                    try {
                        double budget = scan.nextDouble();
                        Party birthday = new Birthday(budget);
                        birthday.createParty();
                        menu();
                    } catch (ImagingOpException | InputMismatchException e) {
                      System.out.println("Podaj liczbę z przecinkiem lub liczbę calkowitą!");
                        menu();
                        break;
                    }break;
                }
                case 2:
                    flag = false;
                    scan.close();
                    break;
            }
        }
    }
    public static void menu() {
        System.out.println("MENU");
        System.out.println("1. Sprawdz na jaką impreze możesz sobie pozwolić");
        System.out.println("2. Wyjdż");
    }
}
MENU
1. Sprawdz na jaką impreze możesz sobie pozwolić
2. Wyjdż
1
Podaj budżet:
123,67
W plenerze

Jak widać w zależności od budżetu utworzony obiekt klasy Birthday wybrał odpowiednią strategię. Użycie tego wzorca spowodowało, że jest możliwe dodawanie nowych strategii bez konieczności zmian w klasach.

Podsumowując wzorzec strategia definiuje rodziny algorytmów, dokonuje ich hermetyzacji i powoduje, że stają się one wymienne. Pozwala również na modyfikacje danego algorytmu niezależnie od klienta, który tego algorytmu używa.

pliki do pobrania:
Birthday Download
BirthdayStrategy Download