So i created a simple visitor pattern for liquids. Such as Milk,juice and liquor.
a Milk class can look like this:
public class Milk implements Visitable{
public float tax=0;
@Override
public int price() {
return 4;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
//and likewise for juice and liquor
and then we can have a visitor which looks like this to do the work of calculating taxes :
public class TaxVisitor implements Visitor {
double taxPerentLiquor=.18;
double taxPerentMilk=.15;
double taxPerentJuice=.10;
@Override
public void visit(Liquor liquor) {
int price =liquor.price();
liquor.setTax((float) (price*taxPerentLiquor));
}
@Override
public void visit(Milk milk) {
float price =milk.price();
milk.setTax((float) (price*taxPerentMilk));
}
@Override
public void visit(Juice juice) {
int price =juice.price();
juice.setTax((float) (price*taxPerentJuice));
}
}
and when we are using it we would do this:
Visitor taxVisitor = new TaxVisitor();
Milk milk = new Milk();
Juice juice = new Juice();
milk.accept(taxVisitor);
juice.accept(taxVisitor);
and a "visitor" would calculate the tax for each liquid for me. and i see the benefit that i do not have to modify the collection of objects themselves when i want to add a new calculation. But my trouble comes when i want to add a new method. Following open closed principle i should not be adding new methods to the milk class for example. But let us imagine i want to add functionality to know what color the liquid is. So i'd like to extend the milk object to have a method called "getColor()" which would return "#FFFFFF". This seems like i would need a decorator pattern to add this functionality if i want to follow SOLID open closed principle. Is there a way to do this with visitor pattern ?