如何摆脱instanceof?

bvjxkvbb  于 2021-07-03  发布在  Java
关注(0)|答案(3)|浏览(302)

有人告诉我,在下面的代码中使用instanceof like是一种不好的做法,因为它会变得重复,并且很难扩展。不过,我对java还很陌生,也不知道我的备选方案是什么,您建议我如何去掉示例并抽象代码?

void moveit(Vehicle car) {
        if(car instanceof Volvo240){
            volvoPoint.x = (int) car.getXCoordinate();
            volvoPoint.y = (int) car.getYCoordinate();
        }
        if(car instanceof Scania) {
            scaniaPoint.x = (int) car.getXCoordinate();
            scaniaPoint.y = (int) car.getYCoordinate() + 100;
        }
        if(car instanceof Saab95) {
            saabPoint.x = (int) car.getXCoordinate();
            saabPoint.y = (int) car.getYCoordinate() + 200;
        }
        repaint();
    }
t2a7ltrp

t2a7ltrp1#

不知道完整的代码,假设只有这三个子类。最小干扰的方法是利用方法重载:

void moveit(Volvo240 car){
     volvoPoint.x = (int) car.getXCoordinate();
     volvoPoint.y = (int) car.getYCoordinate();
     repaint();
}

void moveit(Scania car){
     volvoPoint.x = (int) car.getXCoordinate();
     volvoPoint.y = (int) car.getYCoordinate() + 100;
     repaint();
}

void moveit(Saab95 car){
     saabPoint.x = (int) car.getXCoordinate();
     saabPoint.y = (int) car.getYCoordinate() + 200;
     repaint();
}

void moveit(Vehicle car){
     repaint();
}

在我看来 volvoPoint.x 以及 volvoPoint.y 应该属于这个班 Volvo240 (其他变量也是如此)。但是你保留了那些变量(应该属于类) Volvo240 , Scania ,和 Saab95 )在一个地方,所以(我想)你可以 repaint 基于这些变量的值。
你应该考虑另一种方法,在这种方法中你教每一个人 Vehicle 如何 repaint 他们自己。因此,移动 repaint 相应地,逻辑和这些变量分配给每个子类:

public class Volvo240 extends Vehicle{

       public repaint(){
              volvoPoint.x = (int) car.getXCoordinate();
              volvoPoint.y = (int) car.getYCoordinate();
              // do the repaint logic
       } 
}
9ceoxa92

9ceoxa922#

我要说的是,我对你最初的解决方案没有异议。更多关于这一点在这篇文章的底部。如果您真的希望当前代码不使用 instanceof ,这里有一个方法。
您可以创建一个新类来存储与每种类型车辆相关的信息,如下所示:

public class VehicleInfo {
    private final Point point;
    private final int offset;

    public VehicleInfo(Point point, int offset) {
        this.point = point;
        this.offset = offset;
    }

    public Point getPoint() {
        return point;
    }

    public int getOffset() {
        return offset;
    }
}

然后可以在方法中使用该类,如下所示:

private static final HashMap<Type, Point> POINT_MAP = new HashMap<Type, Point>() {
    {
        put(Volvo240.class, new VehicleInfo(volvoPoint, 0));
        put(Scania.class, new VehicleInfo(scaniaPoint, 100));
        put(Saab95.class, new VehicleInfo(saabPoint, 200));
    }
};

void moveit(Vehicle car) {
    VehicleInfo info = POINT_MAP.get(car.getClass());
    info.getPoint().x = car.getXCoordinate();
    info.getPoint().y = car.getYCoordinate() + info.getOffset();
    repaint();
}

也就是说,我真的没有问题,你原来的解决方案使用 instanceof . 程序必须在某个时候检查参数的类型,所以最好在代码中显式地显示它。除非程序的这一部分要反复修改,而且这是某个大型项目的一部分,每个人都需要使用标准编码约定,否则我只会坚持你所拥有的,不管其他人怎么说。我最近被介绍到雅格尼的概念,我认为这在这里绝对适用。如果成功了,就成功了。

vjrehmav

vjrehmav3#

一旦发生这种情况,就很难引进一种新型汽车。你必须找到所有你检查过的地方,然后用新车改装。见“扩展开放,修改关闭”原则。
你应该有一个接口

interface Vehicle {
  Integer getXCoordinate();
  Integer getYCoordinate();
  void moveIt(Point point);
}

以及三种实现,saab95、volvo240和scania

class Saab95 implements Vehicle {
   moveIt(Point point) {
      point.x = getXCoordinate();
      point.y= getYCoordinate() + 200
   }
}

其他车也是如此

相关问题