I just learned about the Decorator Pattern. I'm trying to implement a method which always leads to a NullPointerException. I've been looking for missing parameters, but I couldn't find anything. The QuackBehavior seems to "disappear" as soon as I try to apply two Decorators to a Duck Object. Thanks in advance!
PS: The NullPointerException didn't seem to appear when I set the attributes (Duck) to public and let the getters stay the same. But that won't work for me since I want to parse to an XML file later.
Exception in thread "main" java.lang.NullPointerException
    at de.ostfalia.swt.progaufgabe_4.HoarseDuckDecorator.quack(HoarseDuckDecorator.java:12)
    at de.ostfalia.swt.progaufgabe_4.App.main(App.java:25)
Duck
public abstract class Duck{
    private QuackBehavior quack;
    private FlyBehavior fly;
    private DuckState state;
    public Duck() {
        setState(DuckState.STANDING);
    }
    public void fly() {
        getFly().fly(this);
    }
    public void land() {
        getFly().land(this);
    }
    public String quack() {
        return quack.quack();
    }
    public void setQuackBehavior (QuackBehavior quack) {
        this.quack = quack;
    }
    public void setFlyBehavior (FlyBehavior fly) {
        this.setFly(fly);
    }
    public QuackBehavior getQuackBehavior() {
        return this.quack;
    }
    public void setState (DuckState state) {
        this.state = state;
    }
    public DuckState getState() {
        return state;
    }
    public FlyBehavior getFly() {
        return fly;
    }
    public void setFly(FlyBehavior fly) {
        this.fly = fly;
    }
}
QuackBehavior
public abstract class QuackBehavior {
    public String geräusch;
    public QuackBehavior() {
        this.geräusch = "";
    }
    public String quack() {
        return this.geräusch;
    }
    public void setGeräusch(String s) {
    }
}
Quack (certain QuackBehavior)
public class Quack extends QuackBehavior {
    String geräusch = "Quack!";
    public String quack() {
        return geräusch;
    }
    public void setGeräusch(String s) {
        this.geräusch = s;
    }
}
Quiek (certain QuackBehavior)
public class Quiek extends QuackBehavior {
    String geräusch = "Quiek!";
    public String quack() {
        return geräusch;
    }
    public void setGeräusch(String s) {
        this.geräusch = s;
    }
FlyBehavior
public abstract class FlyBehavior {
    public void fly(Duck parent) {
    }
    public void land(Duck parent) {
    }
}
FlyWithWings (certain FlyBehavior)
public class FlyWithWings extends FlyBehavior{
    public void fly(Duck parent) {
        if (parent.getState().equals(DuckState.STANDING)){
            parent.setState(DuckState.FLYING);
        }
    }
    public void land(Duck parent) {
        if (parent.getState().equals(DuckState.FLYING)){
            parent.setState(DuckState.STANDING);
        }
    }
}
FlyNot (certain FlyBehavior)
public class FlyNot extends FlyBehavior {
    public void fly(Duck parent) {
    }
    public void land(Duck parent) {
    }
}
DuckState
public enum DuckState {
    FLYING, STANDING;
}
RedheadDuck (actual Duck)
public class RedheadDuck extends Duck{
    private FlyWithWings fly;
    private Quack quack;
    public RedheadDuck() {
        this.fly = new FlyWithWings();
        this.quack = new Quack();
    }
}
RubberDuck (not actually a real Duck)
public class RubberDuck extends Duck {
    private FlyNot fly;
    private Quiek quack;
    public RubberDuck() {
        this.fly = new FlyNot();
        this.quack = new Quiek();
    }
}
App (the snippet I am running)
public class App {
    public static void main(String[] args) {
        Duck duck = new ChattyDuckDecorator(new MallardDuck()); 
        duck = new HoarseDuckDecorator(duck);
        ducksim.addDuck(duck);
        System.out.println(duck.quack());  //NullPointerException   
    }
}
DuckDecorator
public abstract class DuckDecorator extends Duck {
    public Duck specialDuck;
    public DuckDecorator(Duck ducky) {
        this.specialDuck = ducky;
    }
    public String quack(Duck ducky) {
        return specialDuck.quack();
    }
}
HoarseDuckDecorator (Delete aeiou/This is where the NullPointerException occurs)
public class HoarseDuckDecorator extends DuckDecorator {
    public HoarseDuckDecorator(Duck ducky) {
        super(ducky);
    }
    public String quack() {
        this.specialDuck.getQuackBehavior().setGeräusch(specialDuck.getQuackBehavior().quack().replaceAll("(?i)[aeiou]", "")); //NullPointerException
        return specialDuck.quack();
    }
}
ChattyDuckDecorator(Multiply the String)
public class ChattyDuckDecorator extends DuckDecorator {
    public ChattyDuckDecorator(Duck ducky) {
        super(ducky);
    }
    public String quack() {
        specialDuck.getQuackBehavior().setGeräusch(specialDuck.getQuackBehavior().quack() + specialDuck.getQuackBehavior().quack());
        return specialDuck.quack();
    }
}
