I always tend to run into the following design problem that I'm never quite sure how to best resolve. It usually starts with a hierarchy of Animals at my Circus:
Animal
Cat
BigCat
Dog
Elephant
...
Now, each Animal needs to be trained, so that there is a separate method for each:
public interface Trainer {
void train( BigCat animal );
void train( Dog animal );
void train( Elephant animal );
// ...
}
开发者_StackOverflow
The problem is that the CircusDirector doesn't give a damn. He just throws Animals to the Trainer without even looking.
public class CircusDirector {
public void work() {
Trainer trainer = getTrainer();
Animal animal = getAnimal();
// ...and he doesn't know a frog from a pony,
// so he tries to just:
trainer.train(animal);
}
}
Now, the Trainer can get an additional method like
void train( Animal animal );
where he'll use instanceof
to send the animal to the appropriate method, but this seems ugly and doesn't come recommended. Is there a better solution using generics?
You've essentially implemented half of the visitor pattern. You can have each of your Animal's provide an acceptTrainer(Trainer t)
method which then call t.train(this);
Your Director would then call animal.acceptTrainer(trainer);
Also, I think generics info gets compiled out, so you can't do any fancy stuff relying on them. It's best to get familiar with some of the patterns.
What you're describing looks like it could be solved quite neatly with the Visitor pattern or, a little more precisely, double-dispatch.
Have your animals implement a Trainable interface:
interface Trainable {
accept(Trainer trainer);
}
with an implementation like:
public Dog extends Animal implements Trainable {
//... other dog stuff
public accept(Trainer trainer) {
trainer.train(this);
}
}
And then keep the trainer the same way. All the animals will get dispatched appropriately.
精彩评论