Reputation: 15351
I have the following base interface:
public interface Value{
double getValue();
}
I would like to have a few different Outputter
interfaces that would take a Collection and output them, based on the CONCRETE type of the Value, so I could have a Value class that would have 10 other important fields, which should also be output. I know this falls nicely into a Visitor pattern, but my concern is this: Each outputter would always get a list of ONE specific type of Value, SO I could, in theory, supply a typed list of MeanValue, StdDevValue etc. I am not sure how to design this nicely, as Values are generated by another interface, so in fact, I am only holding a reference to Collection, and I do not want to downcast it and then call specific method on the Outputter...
Upvotes: 1
Views: 150
Reputation: 47243
The Visitor pattern doesn't involve any casting. That's the point of it.
Here's the core of a Visitorised family of values:
interface Value {
double getValue();
void accept(ValueVisitor visitor);
}
interface ValueVisitor {
public void visit(MeanValue value);
public void visit(StdDevValue value);
}
class MeanValue implements Value {
@Override
public double getValue() {
// whatever
}
@Override
public void accept(ValueVisitor visitor) {
visitor.visit(this);
}
}
class StdDevValue implements Value {
@Override
public double getValue() {
// whatever
}
public int getDegreesOfFreedom() {
// here's a subclass-specific method
}
@Override
public void accept(ValueVisitor visitor) {
visitor.visit(this);
}
}
Here's the output bit:
abstract class Outputter implements ValueVisitor {
public void output(Collection<? extends Value> values) {
for (Value value : values) {
value.accept(this);
}
}
}
class PrintingOutputter extends Outputter {
@Override
public void visit(MeanValue value) {
System.out.println("Mean: " + value.getValue());
}
@Override
public void visit(StdDevValue value) {
System.out.println("Std Dev: " + value.getValue() + " (" + value.getDegreesOfFreedom() + ")");
}
}
You can use an Outputter
with either a collection of mixed values, or a collection of a specific kind:
List<Value> mixedValues = /* whatever */;
outputter.accept(mixedValues);
List<MeanValue> meanValues = /* whatever */ ;
outputter.accept(meanValues);
Upvotes: 1
Reputation: 272367
Isn't this just simple polymorphism ? i.e. you want each concrete class to implement Outputter
appropriately.
public interface Outputter {
String output(); // implement this...
}
A visitor pattern is designed for mediation between the calling class and the called class. So the calling class calls a method and passes itself, and the called (visited) class calls back.e.g.
public interface Outputter {
String output(Caller c); // implement this...
}
and an implementation may look like:
public String output(Caller c) {
c.doWhatever(getValue());
c.doAnotherThing(getAnotherValue());
}
Note how the implementation differs for each implementation (type) of Outputter
Upvotes: 0