Wzorzec projektowy State

Zadanie Programistyczne

Smoki leżące w szpitalu muszą być monitorowane co do stanów odżywienia.
Stanów jest trzy.
Rozwiązanie

  1. Utworzyć Smoka, który może przyjmować określone stany i może
    pobierać i wydatkować energię.
  2. Utworzyć klasę Stan dla konkretnego Smoka zawierającą ogólne metody
    dodawania i wydatkowania kalorii.
  3. Utworzyć trzy klasy po jednej dla każdego stanu. Klasy dziedziczą po klasie Stan.
    Należy nadpisać metody dotyczące pobierania i wydatkowania energii. Należy uwzględnić zmianę stanu Smoka, o ile zachodzi taka zmiana.
  4. Uruchomić i sprawdzić działanie.

Klasy

Klasa Smok
package state;
class Smok {
    public static final double MAX_STAN_KALORII = 60000.0;
    public static final double MIN_STAN_KALORII = 30000.0;
    public static final String ERROR = "Error: Koniec zapasu energii";
    public static final String ERROR_UP = "Error: Koniec jedzenia. "
            + "Stan zagrażający życiu";
    private Stan stanPacjenta;
    private final String nrLozka;
    private double stanOdzywienia;
    public Smok(String nrLozka) {
        this.nrLozka = nrLozka;
        stanPacjenta = Stan.stanPoczatkowy(this);
    }
    public void setState(Stan stanPacjenta) {
        this.stanPacjenta = stanPacjenta;
    }
    private Stan getStanPacjenta() {
        return stanPacjenta;
    }
    public String getNrLozka() {
        return nrLozka;
    }
    public boolean dodajKalorie(double liczbaKalorii) {
        return getStanPacjenta().dodajKalorie(liczbaKalorii);
    }
    public boolean wydatkujKalorie(double liczbaKalorii) {
        return getStanPacjenta().wydatkujKalorie(liczbaKalorii);
    }
    public double getStanOdzywienia() {
        return stanOdzywienia;
    }
    public void setStanOdzywienia(double stanOdzywienia) {
        this.stanOdzywienia = stanOdzywienia;
    }
}
Klasa Stan
package state;
public class Stan {
    private Smok smok;
    Stan(Smok smok) {
        this.smok = smok;
    }
    Stan(Stan stan) {
        this.smok = stan.getSmok();
    }
    Smok getSmok() {
        return smok;
    }
    public void setSmok(Smok smok) {
        this.smok = smok;
    }
    public static Stan stanPoczatkowy(Smok smok) {
        return new StanAktywnosci(smok);
    }
    public boolean dodajKalorie(double liczbaKalorii) {
        double bilansKalorii = getSmok().getStanOdzywienia() + liczbaKalorii;
        getSmok().setStanOdzywienia(bilansKalorii);
        System.out.println("Smok pobrał " + liczbaKalorii + " kalorii ");
        return true;
    }
    public boolean wydatkujKalorie(double liczbaKalorii) {
        double bilansKalorii = getSmok().getStanOdzywienia() - liczbaKalorii;
        getSmok().setStanOdzywienia(bilansKalorii);
        System.out.println("Smok wydatkował " + liczbaKalorii + " kalorii ");
        return true;
    }
    @Override
    public String toString() {
        return this.getClass().getSimpleName();
    }
}
Klasa StanAktywnosci
package state;
public class StanAktywnosci extends Stan {
    public StanAktywnosci(Smok smok) {
        super(smok);
    }
    public StanAktywnosci(Stan stan) {
        super(stan);
        System.out.println("stan aktywności");
    }
    @Override
    public boolean dodajKalorie(double liczbaKalorii) {
        double bilansKalorii = getSmok().getStanOdzywienia() + liczbaKalorii;
        if (bilansKalorii > Smok.MAX_STAN_KALORII) {
            getSmok().setState(new StanPrzekarmienia(this));
        }
        return super.dodajKalorie(liczbaKalorii);
    }
    @Override
    public boolean wydatkujKalorie(double liczbaKalorii) {
        double bilansKalorii = getSmok().getStanOdzywienia() - liczbaKalorii;
        if ((bilansKalorii) >= Smok.MIN_STAN_KALORII) {
            super.wydatkujKalorie(liczbaKalorii);
            return true;
        } else if ((bilansKalorii) < Smok.MIN_STAN_KALORII) {
            getSmok().setState(new StanNiedozywienia(this));
            super.wydatkujKalorie(liczbaKalorii);
            return true;
        } else {
            System.out.println(Smok.ERROR);
            return false;
        }
    }
}
Klasa StanNiedozywienia
package state;
public class StanNiedozywienia extends Stan {
    public StanNiedozywienia(Smok smok) {
        super(smok);
    }
    public StanNiedozywienia(Stan stan) {
        super(stan);
        System.out.println("stan niedożywienia");
    }
    @Override
    public boolean dodajKalorie(double liczbaKalorii) {
        double bilansKalorii = getSmok().getStanOdzywienia() + liczbaKalorii;
        if (bilansKalorii < Smok.MIN_STAN_KALORII) {
            return super.dodajKalorie(liczbaKalorii);
        } else if ((bilansKalorii > Smok.MIN_STAN_KALORII)
                && (bilansKalorii <= Smok.MAX_STAN_KALORII)) {
            getSmok().setState(new StanAktywnosci(this));
            return super.dodajKalorie(liczbaKalorii);
        } else if (bilansKalorii > Smok.MAX_STAN_KALORII) {
            getSmok().setState(new StanPrzekarmienia(this));
            return super.dodajKalorie(liczbaKalorii);
        } else {
            return false;
        }
    }
    @Override
    public boolean wydatkujKalorie(double liczbaKalorii) {
        double bilansKalorii = getSmok().getStanOdzywienia() - liczbaKalorii;
        if ((bilansKalorii) >= Smok.MIN_STAN_KALORII) {
            return super.wydatkujKalorie(liczbaKalorii);
        } else {
            System.out.println(Smok.ERROR);
            return false;
        }
    }
}
Klasa StanPrzekarmienia
package state;
public class StanPrzekarmienia extends Stan {
    public StanPrzekarmienia(Smok smok) {
        super(smok);
    }
    public StanPrzekarmienia(Stan stan) {
        super(stan);
        System.out.println("stan przekarmienia");
    }
    @Override
    public boolean dodajKalorie(double liczbaKalorii) {
        double bilansKalorii = getSmok().getStanOdzywienia() + liczbaKalorii;
        if (bilansKalorii <= Smok.MAX_STAN_KALORII) {
            return super.dodajKalorie(liczbaKalorii);
        } else {
            System.out.println(Smok.ERROR_UP);
            return false;
        }
    }
    @Override
    public boolean wydatkujKalorie(double liczbaKalorii) {
        double bilansKalorii = getSmok().getStanOdzywienia() - liczbaKalorii;
        if (bilansKalorii > Smok.MAX_STAN_KALORII) {
            return super.wydatkujKalorie(liczbaKalorii);
        } else if ((bilansKalorii >= Smok.MIN_STAN_KALORII)
                && (bilansKalorii < Smok.MAX_STAN_KALORII)) {
            getSmok().setState(new StanAktywnosci(this));
            return super.wydatkujKalorie(liczbaKalorii);
        } else {
            getSmok().setState(new StanNiedozywienia(this));
            return super.wydatkujKalorie(liczbaKalorii);
        }
    }
}
Klasa Main
package state;
class Main {
    public static void main(String[] args) {
        Smok smok = new Smok("45");
        smok.dodajKalorie(20000);
        smok.dodajKalorie(20000);
        smok.dodajKalorie(20000);
        smok.dodajKalorie(20000);
        smok.dodajKalorie(20000);
        smok.wydatkujKalorie(30000);
        smok.wydatkujKalorie(30000);
    }
}

Wynik

Smok pobrał 20000.0 kalorii
Smok pobrał 20000.0 kalorii
Smok pobrał 20000.0 kalorii
stan przekarmienia
Smok pobrał 20000.0 kalorii
Error: Koniec jedzenia. Stan zagrażający życiu
stan aktywności
Smok wydatkował 30000.0 kalorii
stan niedożywienia
Smok wydatkował 30000.0 kalorii