Шаблон посетителя - это в основном механизм разрешения поведения по многим причинам. Чтобы быть полезным/применимым к вашему примеру с животными, нам нужно добавить посетителя, как указал Энди Тернер.
Как насчет включения «Тренеры животных» в качестве посетителей? Различные тренеры-животные могли заставить разных животных говорить по-другому (или нет).
Итак, во-первых, сущность (интерфейс для животных). Мне нравится думать об этом как «Вещи» быть «действовало Актер»:
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):
Cat:
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!");
}
}
Теперь давайте тянуть все это вместе и заведите всех тренеров по животным (Фил и Джек), чтобы заставить всех животных (Кошка, Собака, Пудель) поговорить через класс менеджера:
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!
Это делает его относительно легко добавлять новые тренер, которые имеют доступ к конкретным вещам животного типа (например, если вы добавили коготь информации для кошек и лапы Информации для собак , ...), поскольку они действуют на разных животных. Я думаю, что проблема с традиционным примером «посетителя» - слишком туманная и недостаточно конкретная. Пример такси не сделал это для меня. Надеюсь, этот пример поможет.
какое описание шаблона посетителя вы использовали? – wero
Если вы хотите пройти через список как Животные и не переопределять функции, вы должны проверить с помощью 'instanceof', а затем отбросить объект. Например, внутри вашего списка 'if (экземпляр cat) {visitor.talk (((Cat) a) .talk()}'. Но я ВЫ рекомендую просто переопределить метод, так как вы уже используете inheretance –
Как ненавистник шаблон посетителя, я спрашиваю, почему бы просто не полагаться на типичную иерархию интерфейса/класса, а не накладывать на него шаблон? – ChiefTwoPencils