如何避免Java中的instanceof检查

时间:2015-01-26 17:39:51

标签: java instanceof visitor-pattern

我有以下类结构:

class Thing {
}

abstract class Pet extends Thing {
    void eat(Thing thing) {
       // do something
    }
}

class Tiger extends Pet {
    void eat(Thing thing) {
        if (thing instanceOf Creature)
             // do Something
        else
             super.eat(thing);
    }
}

我想避免来自子类Tiger的检查实例?有没有办法实现这个目标?如何使用访客模式替换它?

Thing是一个基类。 Pet是一个抽象类,其方法为eat()。 子类Tiger想要一个eat方法的具体实现。

2 个答案:

答案 0 :(得分:2)

使用Map

尝试此解决方案
import java.util.Map;
import java.util.HashMap;

interface ToDo {
  void exec();
}

abstract class Animal {}

class Tiger extends Animal {}

class Dog extends Animal {}

class Ideone {
  public static void main(String[] args) {
    Map <Class, ToDo> map = new HashMap <Class, ToDo>();
    map.put(Tiger.class, new ToDo() {
        public void exec() {
            System.out.println("do for tiger ...");
        }
    });
    map.put(Dog.class, new ToDo() {
        public void exec() {
            System.out.println("do for dog ...");
        }
    });
    for(Animal a : new Animal[]{new Tiger(), new Dog(), null}) {
        try {
            map.get(a.getClass()).exec();
        } catch (NullPointerException npe) {
            System.out.println("nothing to do ...");
        }
    }
  }
}

答案 1 :(得分:1)

我可以想到几个解决方案:

  1. 将支票移至Thing:if (thing.isEatable())
  2. 如果不能食用,那就扔掉一个例外:try { eat(thing); } catch …
  3. 不要以为所有宠物都可以吃东西。从pet中移除eat(Thing)方法,并将eat(Creature)eat(Food)方法添加到Tiger
  4. 将逻辑移至Thing。致电thing.beingEaten(),并在Creature中覆盖该方法以致电doSomething而非eat
  5. 编辑:

    如果事物是​​doOneThing()

    ,如何调用Creature

    使用instanceof:

    class Tiger extends Pet {
        void eat (Thing thing) {
            if (thing is instanceOf Creature) {
                doOneThing();
            } else {
                doOtherThing();
            }
        }
    }
    

    没有instanceof:

    class Tiger extends Pet {
        void eat(Thing thing) {
            thing.beEaten();
        }
    }
    
    class Creature extends Thing {
        void beEaten() {
            doOneThing();
        }
    }
    
    class Thing {
        void beEaten() {
            doOtherThing();
        }
    }