问题描述
动物
public abstract class Animal {
String name;
public Animal(String name) {
this.name = name;
}
}
狮子
public class Lion extends Animal {
public Lion(String name) {
super(name);
// TODO Auto-generated constructor stub
}
public void roar() {
System.out.println("Roar");
}
}
鹿
public class Deer extends Animal {
public Deer(String name) {
super(name);
}
public void runAway() {
System.out.println("Running...");
}
}
测试动物
public class TestAnimals {
public static void main(String[] args) {
Animal lion = new Lion("Geo");
Animal deer1 = new Deer("D1");
Animal deer2 = new Deer("D2");
List<Animal> li = new ArrayList<Animal>();
li.add(lion);
li.add(deer1);
li.add(deer2);
for (Animal a : li) {
if (a instanceof Lion) {
Lion l = (Lion) a;
l.roar();
}
if (a instanceof Deer) {
Deer l = (Deer) a;
l.runAway();
}
}
}
}
有没有更好的方法来遍历列表而不必强制转换?在上面的例子中看起来没问题,但是如果你有很多基类的扩展,那么我们也需要那么多的 if 块.有没有设计解决这个问题的模式或原则?
Is there a better way to iterate through the list without having to cast ?In the above case it seem's ok but if you have many extensions of the base class then we'll need that many if block too.Is there a design pattern or principle to address this problem ?
推荐答案
一种避免 instanceof
的优雅方式,而无需在基类中发明一些新的人工方法(使用非描述性名称,例如 performAction
或 doWhatYouAreSupposedToDo
) 是使用访问者模式.下面是一个例子:
An elegant way of avoiding instanceof
without inventing some new artificial method in the base class (with a non-descriptive name such as performAction
or doWhatYouAreSupposedToDo
) is to use the visitor pattern. Here is an example:
动物
import java.util.*;
abstract class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public abstract void accept(AnimalVisitor av); // <-- Open up for visitors.
}
狮子和鹿
class Lion extends Animal {
public Lion(String name) {
super(name);
}
public void roar() {
System.out.println("Roar");
}
public void accept(AnimalVisitor av) {
av.visit(this); // <-- Accept and call visit.
}
}
class Deer extends Animal {
public Deer(String name) {
super(name);
}
public void runAway() {
System.out.println("Running...");
}
public void accept(AnimalVisitor av) {
av.visit(this); // <-- Accept and call visit.
}
}
访客
interface AnimalVisitor {
void visit(Lion l);
void visit(Deer d);
}
class ActionVisitor implements AnimalVisitor {
public void visit(Deer d) {
d.runAway();
}
public void visit(Lion l) {
l.roar();
}
}
测试动物
public class TestAnimals {
public static void main(String[] args) {
Animal lion = new Lion("Geo");
Animal deer1 = new Deer("D1");
Animal deer2 = new Deer("D2");
List<Animal> li = new ArrayList<Animal>();
li.add(lion);
li.add(deer1);
li.add(deer2);
for (Animal a : li)
a.accept(new ActionVisitor()); // <-- Accept / visit.
}
}
这篇关于如何避免大的 if 语句和 instanceof的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!