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 ?
TaxVisitor: the visitor would need to maintain any state not maintained by the elements. Hence, if none of the liquids maintained their own color, aColorVisitorwould have to maintain all of them. It's possible, but not practical.getColor()to your liquids does not violate O/C. That's the purpose of "open for extension": you can still add behaviors, as long as they don't affect any existing behavior. If you affect existing code, any code that depends on it may also be affected, which could potentially break contracts (thus break software). If addinggetColor()doesn't affect any working code, then it's not a principle violation, it's scaling up. Look at the first bullet point from this link