This means the base object is added with additional responsibility which is a vanilla flavor in this case. If another customer wants a chocolate flavor, the vendor will add the chocolate flavor ice cream as the additional responsibility at the run time.
So, when the object should be treated dynamically at the run time based on the criteria, then we should choose Decorator Design Pattern.
public interface Pizza { public void getPizza(); }
public class MushroomPizza implements Pizza { @Override public void getPizza() { System.out.print("Mushroom Pizza"); } }
public class ChickenPizza implements Pizza { @Override public void getPizza() { System.out.print("Chicken Pizza"); } }
public abstract class PizzaDecorator implements Pizza { protected Pizza pizza; public PizzaDecorator(Pizza pizza) { this.pizza=pizza; } @Override public void getPizza() { this.pizza.getPizza(); } }
public class PizzaWithToppings extends PizzaDecorator { public PizzaWithToppings(Pizza pizza) { super(pizza); } @Override public void getPizza() { pizza.getPizza(); addToppings(); } private void addToppings() { System.out.print(" with toppings"); } }