我尝试在扩展类中使用访问者模式。我有动物类的列表,每个类都是不同的动物。当我调用访问者时,它将只执行talk(Animal a),而不是对象的具体实例。如下所示:
class Animal {}
class Cat extends Animal {}
class Dog extends Animal {}
class Poodle extends Dog {}
class Visitor {
public void talk(Animal a) { System.out.println("?"); }
public void talk(Cat a) { System.out.println("Meow"); }
public void talk(Dog a) { System.out.println("bark"); }
public void talk(Poodle a) { System.out.println("Arf"); }
}
public class Demo{
public static void main(String []args){
Visitor visitor = new Visitor();
Animal list[] = { new Cat(), new Dog(), new Poodle() };
for (Animal a : list)
visitor.talk(a);
}
}输出为:
?
?
?虽然我期望:
Meow
bark
Arf 你知道如何在不把很多instanceof放在一个talk()方法中的情况下实现访问器吗?
发布于 2016-02-05 17:26:55
Visitor pattern的一个关键元素是double-dispatch:您需要从实际的子类中调用访问者方法
abstract class Animal {
abstract void accept(Visitor v);
}
class Dog extends Animal {
@Override void accept(Visitor v) { v.talk(this); }
}
// ... etc for other animals.然后,将访问者传递给动物,而不是将动物传递给访问者:
for (Animal a : list)
a.accept(visitor);这样做的原因是编译器选择调用Visitor上的重载-它在运行时不会被选中。编译器只知道a是一个Animal,所以它知道可以安全调用的唯一方法就是Visitor.visit(Animal)重载。
发布于 2016-04-09 03:19:26
访问者模式基本上是一种多对多类行为解析机制。为了对你的动物例子有用/适用,我们需要添加一个访问者,正如Andy Turner所指出的那样。
加入“动物训练师”作为访客怎么样?不同的动物训练师可以让不同的动物说话不同(或不同)。
所以,首先,实体(动物接口)。我喜欢把它想象成一个“被演员扮演”的“事物”:
public interface IAnimal {
public String getAnimalName();
// aka... public void accept(Visitor v)
public void allowAnimalTrainerToMakeMeSpeak(IAnimalTrainer animalTrainer);
}然后让我们定义一个访问者类型(动物训练器接口)。我喜欢把访问者想象成一个作用于各种“事物”(实体)的“演员”:
public interface IAnimalTrainer {
public String getTrainerName();
//aka... public void visit(Dog dog);
public void animalTrainerMakesAnimalSpeak(Dog dog);
public void animalTrainerMakesAnimalSpeak(Cat cat);
public void animalTrainerMakesAnimalSpeak(Poodle poodle);
}现在让我们创建动物(实现IAnimal接口):
猫:
public class Cat implements IAnimal {
private String animalName;
@Override
public String getAnimalName() {
return animalName;
}
public void setAnimalName(String animalName) {
this.animalName = animalName;
}
public Cat(String animalName) {
this.animalName = animalName;
}
public Cat() {
// Default constructor
}
@Override
public void allowAnimalTrainerToMakeMeSpeak(IAnimalTrainer animalTrainer) {
animalTrainer.animalTrainerMakesAnimalSpeak(this);
}
}狗:
public class Dog implements IAnimal {
private String animalName;
@Override
public String getAnimalName() {
return animalName;
}
public void setAnimalName(String animalName) {
this.animalName = animalName;
}
public Dog(String animalName) {
this.animalName = animalName;
}
public Dog() {
// Default constructor
}
@Override
public void allowAnimalTrainerToMakeMeSpeak(IAnimalTrainer animalTrainer) {
animalTrainer.animalTrainerMakesAnimalSpeak(this);
}
}贵宾犬:
public class Poodle extends Dog {
public Poodle(String animalName) {
super(animalName);
}
public Poodle() {
super();
}
@Override
public void allowAnimalTrainerToMakeMeSpeak(IAnimalTrainer animalTrainer) {
animalTrainer.animalTrainerMakesAnimalSpeak(this);
}
}现在让我们创建动物训练师,菲尔和杰克(实现IAnimalTrainer接口):
动物训练师菲尔:
public class AnimalTrainerPhil implements IAnimalTrainer {
private String trainerName = "Phil";
@Override
public String getTrainerName() {
return trainerName;
}
public void setTrainerName(String trainerName) {
this.trainerName = trainerName;
}
@Override
public void animalTrainerMakesAnimalSpeak(Dog dog) {
System.out.println(
"Animal trainer "
+ getTrainerName()
+ " gets "
+ dog.getAnimalName()
+ " the dog to say: BARK!!");
}
@Override
public void animalTrainerMakesAnimalSpeak(Cat cat) {
System.out.println(
"Animal trainer "
+ getTrainerName()
+ " gets "
+ cat.getAnimalName()
+ " the cat to say: MEOW!!");
}
@Override
public void animalTrainerMakesAnimalSpeak(Poodle poodle) {
animalTrainerMakesAnimalSpeak((Dog)poodle);
}
}动物训练师杰克:
public class AnimalTrainerJack implements IAnimalTrainer {
private String trainerName = "Jack";
@Override
public String getTrainerName() {
return trainerName;
}
public void setTrainerName(String trainerName) {
this.trainerName = trainerName;
}
@Override
public void animalTrainerMakesAnimalSpeak(Dog dog) {
System.out.println(
"Animal trainer "
+ getTrainerName()
+ " gets "
+ dog.getAnimalName()
+ " the dog to say: Bark bark.");
}
@Override
public void animalTrainerMakesAnimalSpeak(Cat cat) {
System.out.println(
"Animal trainer "
+ getTrainerName()
+ " gets "
+ cat.getAnimalName()
+ " the cat to say: Meoooow.");
}
@Override
public void animalTrainerMakesAnimalSpeak(Poodle poodle) {
System.out.println(
"Animal trainer "
+ getTrainerName()
+ " gets "
+ poodle.getAnimalName()
+ " the poodle to say: Yip! Yip!");
}
}现在,让所有的动物训练师(Phil和Jack)通过一个Manager类让所有的动物(猫、狗、贵宾犬)都能说话:
public class ManagerOfAnimalTrainersAndAnimals {
public static void main(String[] args) {
ArrayList<IAnimal> allAnimals = new ArrayList<>();
allAnimals.add(new Dog("Henry"));
allAnimals.add(new Cat("Priscilla"));
allAnimals.add(new Poodle("Spike"));
ArrayList<IAnimalTrainer> allAnimalTrainers = new ArrayList<>();
allAnimalTrainers.add(new AnimalTrainerPhil());
allAnimalTrainers.add(new AnimalTrainerJack());
// Allow all animal trainers to get each animal to speak
for (IAnimalTrainer animalTrainer : allAnimalTrainers) {
for (IAnimal animal : allAnimals) {
animal.allowAnimalTrainerToMakeMeSpeak(animalTrainer);
}
}
}
}下面是输出:
Animal trainer Phil gets Henry the dog to say: BARK!!
Animal trainer Phil gets Priscilla the cat to say: MEOW!!
Animal trainer Phil gets Spike the dog to say: BARK!!
Animal trainer Jack gets Henry the dog to say: Bark bark.
Animal trainer Jack gets Priscilla the cat to say: Meoooow.
Animal trainer Jack gets Spike the poodle to say: Yip! Yip!这使得添加新的训练师相对容易,他们可以访问动物类型的特定内容(例如,如果您将爪子信息添加到猫,将爪子信息添加到狗,……)当它们作用于各种动物时。我认为传统的“访问者”示例的问题在于它太模糊,不够具体。出租车的例子也不适合我。我希望这个例子能有所帮助。
https://stackoverflow.com/questions/35220362
复制相似问题