如何避免大型 if 语句和实例

2022-09-02 05:10:07

动物

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

  }
 }
}

有没有更好的方法来迭代列表而不必强制转换?在上面的例子中,这似乎是可以的,但是如果你有基类的许多扩展,那么我们也需要那么多的扩展。是否有设计模式或原则来解决这个问题?


答案 1

避免在基类中发明一些新的人工方法(具有非描述性名称,如or)的优雅方法是使用访问者模式。下面是一个示例:instanceofperformActiondoWhatYouAreSupposedToDo

动物

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

答案 2

动物

public abstract class Animal {
 String name;

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

 public abstract void exhibitNaturalBehaviour();

}

狮子

public class Lion extends Animal {

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

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

鹿

public class Deer extends Animal {

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

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

}

测试动物

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

 }
}