如何避免使用大型if语句和instanceof

Emi*_*mil 16 java iteration casting

动物

public abstract class Animal {
 String name;

 public Animal(String name) {
  this.name = name;
 }

}
Run Code Online (Sandbox Code Playgroud)

狮子

public class Lion extends Animal {

 public Lion(String name) {
  super(name);
  // TODO Auto-generated constructor stub
 }

 public void roar() {
  System.out.println("Roar");
 }
}
Run Code Online (Sandbox Code Playgroud)

鹿

public class Deer extends Animal {

 public Deer(String name) {
  super(name);
 }

 public void runAway() {
  System.out.println("Running...");
 }

}
Run Code Online (Sandbox Code Playgroud)

TestAnimals

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();
   }

  }
 }
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来迭代遍历列表而不必进行转换?在上面的情况下它似乎没问题,但如果你有很多基类的扩展,那么我们将需要那么多if块.是否有设计模式或原则解决这个问题?

aio*_*obe 31

避免instanceof在基类中没有发明一些新的人工方法(使用非描述性名称,如performActiondoWhatYouAreSupposedToDo)的优雅方法是使用访问者模式.这是一个例子:

动物

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.

}
Run Code Online (Sandbox Code Playgroud)

狮子鹿

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.
    }

}
Run Code Online (Sandbox Code Playgroud)

游客

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

TestAnimals

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.
    }
}
Run Code Online (Sandbox Code Playgroud)


Ade*_*ari 12

动物

public abstract class Animal {
 String name;

 public Animal(String name) {
  this.name = name;
 }

 public abstract void exhibitNaturalBehaviour();

}
Run Code Online (Sandbox Code Playgroud)

狮子

public class Lion extends Animal {

 public Lion(String name) {
  super(name);
 }

 public void exhibitNaturalBehaviour() {
  System.out.println("Roar");
 }
}
Run Code Online (Sandbox Code Playgroud)

鹿

public class Deer extends Animal {

 public Deer(String name) {
  super(name);
 }

 public void exhibitNaturalBehaviour() {
  System.out.println("Running...");
 }

}
Run Code Online (Sandbox Code Playgroud)

TestAnimals

public class TestAnimals {
 public static void main(String[] args) {

  Animal[] animalArr = {new Lion("Geo"), new Deer("D1"), new Deer("D2")};
  for (Animal a : animalArr) {
     a.exhibitNaturalBehaviour();    
  }

 }
}
Run Code Online (Sandbox Code Playgroud)

  • 建议的替代方法名称:exhibitNaturalBehaviour() (3认同)

Jig*_*shi 5

是的提供了一个action()在抽象类中调用的方法,在两个子类中实现它,一个会咆哮其他会失控