Aria

Wzorzec projektowy Decorator

inne wzorce projektowe

Zadanie programistyczne

Smoki zakładają kawiarnię, gdzie będą podawać 4 ludzkie napoje, z których każdy
może mieć od 0 do 4 dodatków smakowych. Tworzenie kilkunastu klas nie miałoby
sensu, wiec należy wymyślić coś innego.

Rozwiązanie:

Utworzyć abstrakcyjna klasę Potrawa.

Każdy główny napój: kawa, czekolada, kakao, ambrozja – dziedziczy po tej klasie.

Abstrakcyjna klasa Dodatek dziedziczy po klasie Potrawa.

Każdy dodatek: miód, mleko, śmietanka, sok – dziedziczy po klasie Dodatek.

Do każdej potrawy można dodać dowolną ilość dodatków

Koszt składników jest dodawany do potrawy.

Klasy

Pakiet potrawy

Klasa Potrawa
package decorator.potrawy;
public abstract class Potrawa {
	protected String opis = "";
	public String getOpis() {
		return opis;
	}
	public abstract double koszt();
}

Pakiet dodatki

Klasa Dodatek
package decorator.dodatki;
import decorator.potrawy.*;
public abstract class Dodatek extends Potrawa {
	@Override
	public abstract String getOpis();
}
Klasa Miod
package decorator.dodatki;
import decorator.potrawy.*;
public class Miod extends Dodatek {
	private final Potrawa skladnik;
	public Miod(Potrawa skladnik) {
		this.skladnik = skladnik;
	}
	@Override
	public String getOpis() {
		return skladnik.getOpis() + ", Miód";
	}
	@Override
	public double koszt() {
		return .20 + skladnik.koszt();
	}
}
Klasa Mleko
package decorator.dodatki;
import decorator.potrawy.*;
public class Mleko extends Dodatek {
	private final Potrawa skladnik;
	public Mleko(Potrawa skladnik) {
		this.skladnik = skladnik;
	}
	@Override
	public String getOpis() {
		return skladnik.getOpis() + ", Mleko";
	}
	@Override
	public double koszt() {
		return .10 + skladnik.koszt();
	}
}
Klasa Smietanka
package decorator.dodatki;
import decorator.potrawy.*;
public class Smietanka extends Dodatek {
	private final Potrawa skladnik;
	public Smietanka(Potrawa skladnik) {
		this.skladnik = skladnik;
	}
	@Override
	public String getOpis() {
		return skladnik.getOpis() + ", Śmietanka";
	}
	@Override
	public double koszt() {
		return .15 + skladnik.koszt();
	}
}
Klasa Sok
package decorator.dodatki;
import decorator.potrawy.*;
public class Sok extends Dodatek {
	private final Potrawa skladnik;
	public Sok(Potrawa skladnik) {
		this.skladnik = skladnik;
	}
	@Override
	public String getOpis() {
		return skladnik.getOpis() + ", Sok";
	}
	@Override
	public double koszt() {
		return .10 + skladnik.koszt();
	}
}

Pakiet napoje

Klasa Ambrozja
package decorator.napoje;
import decorator.potrawy.*;
public class Ambrozja extends Potrawa {
	public Ambrozja() {
		opis = "Ambrozja";
	}
	@Override
	public double koszt() {
		return 5.99;
	}
}
Klasa Czekolada
package decorator.napoje;
import decorator.potrawy.*;
public class Czekolada extends Potrawa {
	public Czekolada() {
		opis = "Czekolada";
	}
	@Override
	public double koszt() {
		return 5.05;
	}
}
Klasa Kakao
package decorator.napoje;
import decorator.potrawy.*;
public class Kakao extends Potrawa {
	public Kakao() {
		opis = "Kakao";
	}
	@Override
	public double koszt() {
		return 2.89;
	}
}
Klasa Kawa
package decorator.napoje;
        import decorator.potrawy.*;
        public class Kawa extends Potrawa {
        public Kawa() {
        opis = "Kawa";
        }
        @Override
        public double koszt() {
        return 3.99;
        }
        }
        

Wyniki

Klasa Main
package decorator;
        import decorator.dodatki.*;
        import decorator.napoje.*;
        import decorator.potrawy.*;
        class Main {
        public static void main(String args[]) {
        Potrawa potrawa = new Kawa();
        System.out.println(potrawa.getOpis() + " " + potrawa.koszt() + " zł");
        Potrawa potrawa2 = new Ambrozja();
        potrawa2 = new Miod(potrawa2);
        System.out.println(potrawa2.koszt());
        potrawa2 = new Miod(potrawa2);
        System.out.println(potrawa2.koszt());
        potrawa2 = new Sok(potrawa2);
        System.out.println(potrawa2.koszt());
        System.out.println(potrawa2.getOpis() + " " + potrawa2.koszt() + " zł");
        Potrawa potrawa3 = new Kakao();
        potrawa3 = new Smietanka(potrawa3);
        potrawa3 = new Miod(potrawa3);
        potrawa3 = new Sok(potrawa3);
        System.out.println(potrawa3.getOpis() + " " + potrawa3.koszt() + " zł");
        }
        }
        
Kawa 3.99 zł
6.19
6.390000000000001
6.49
Ambrozja, Miód, Miód, Sok 6.49 zł
Kakao, Śmietanka, Miód, Sok 3.3400000000000003 zł

Uwagi

W podanym przykładzie brakuje – dla uproszczenia – setterów i getterów pozwalających
na zmiany opisów i cen.

Do zaokrąglania wyników można użyć mojej metody zaokrąglania liczb double i float.