【问题标题】:How to get rid of instanceof?如何摆脱实例?
【发布时间】:2020-12-07 20:44:56
【问题描述】:

有人告诉我,在下面的代码中使用 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();
    }

【问题讨论】:

    标签: java oop instanceof


    【解决方案1】:

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

    其他车以此类推

    【讨论】:

      【解决方案2】:

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

      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 应该属于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
             } 
      }
      

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-23
          • 1970-01-01
          • 2014-01-28
          • 2013-10-31
          • 2020-10-19
          • 2019-12-01
          相关资源
          最近更新 更多