繁体   English   中英

如何摆脱实例?

[英]How to get rid of instanceof?

有人告诉我,在下面的代码中使用 instanceof 是不好的做法,因为它变得重复并且难以扩展。 我对 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();
    }

InstanceOf 将使推出新型汽车变得困难。 您将必须找到您进行这些实例检查并使用新车进行修改的所有位置。 参见“开放扩展,封闭修改”原则。

你应该有一个界面

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

其他车以此类推

在不知道完整代码的情况下,并假设您只有这三个子类。 侵入性最小的方法是利用方法重载:

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.xvolvoPoint.y应该属于 class Volvo240 (同样适用于其他变量)。 但是您将这些变量(应该属于Volvo240ScaniaSaab95类)保存在一个地方,以便(我假设)您可以根据这些变量的值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
       } 
}

我要直接说,我对您的原始解决方案没有任何问题。 更多关于这篇文章底部的内容。 如果您真的希望您当前的代码在不使用instanceof的情况下工作,这是一种方法。

您可以创建一个新的 class 来存储与每种类型的车辆相关的信息,如下所示:

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

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

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的原始解决方案没有任何问题。 该程序将不得不在某个时候检查参数的类型,因此不妨在您的代码中明确显示这一点。 除非程序的这一部分将被反复修改,并且这是一个每个人都需要使用标准编码约定的大型项目的一部分,否则我会坚持你所拥有的,尽管这里的其他人都在说。 我最近被介绍了YAGNI的概念,我认为这绝对适用于此。 如果它有效,它就有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM