访问者模式基本上是一种多对多的类行为解析机制。为了对您的动物示例有用/适用,我们需要添加一个访客,正如 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);
}
}
现在让我们创建驯兽师 Phil 和 Jack(实现 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!
这使得添加新的训练员变得相对容易,这些训练员可以访问特定动物类型的内容(例如,如果您向猫添加爪信息,向狗添加爪信息,...),因为它们对各种动物采取行动。我认为传统的“访问者”示例的问题在于它太模糊且不够具体。出租车的例子也没有为我做。我希望这个例子有所帮助。