【问题标题】:Proper API implementation when comparing two children of a parent type比较父类型的两个子项时的正确 API 实现
【发布时间】:2013-12-08 01:27:56
【问题描述】:

鉴于以下情况:

public interface Vehicle {
    // Makes this vehicle race another Vehicle and returns who wins the race.
    public Vehicle race(Vehicle otherVehicle);
}

public class Car implements Vehicle {
    @Override
    public Vehicle race(Vehicle otherVehicle) {
        // Different algorithms are used to determine who wins based on
        // what type otherVehicle is.
        if(otherVehicle instanceof Car) {
            // Use algorithm #1 to determine who wins the race
        } else if(otherVehicle instanceof Helicopter) {
            // Use algorithm #2 to determine who wins the race
        } else if(otherVehicle instanceof Motorcycle) {
            // Use algorithm #3 to determine who wins the race
        }

        // ...etc.
    }
}

public class Helicopter implement Vehicle {
    @Override
    public Vehicle race(Vehicle otherVehicle) {
        // Same problem as above with Car.
    }
}

public class Motorcycle implements Vehicle {
    // ... same problem here
}

... lots of other types of Vehicles

由于Car vs. CarCar vs Helicopter 等使用不同的算法,所以race(Vehicle) 方法的实现变得难看并且充满了instanceof 检查...哎呀.

必须有一种更面向对象的方式来做到这一点...想法?

【问题讨论】:

    标签: java oop design-patterns inheritance instanceof


    【解决方案1】:

    您可以使用double dispatch 模式:

    public interface Vehicle {
        // Makes this vehicle race another Vehicle and returns who wins the race.
        public Vehicle race(Vehicle otherVehicle);
        public Vehicle race(Helicopter otherVehicle);
        public Vehicle race(Motorcycle otherVehicle);
        public Vehicle race(Car otherVehicle);
    }
    
    public class Helicopter implement Vehicle {
        @Override
        public Vehicle race(Vehicle otherVehicle) {
            otherVehicle.race(this);
        }
    
        public Vehicle race(Helicopter heli) {
    
        }
        ...
    }
    
    public class Car implement Vehicle {
        @Override
        public Vehicle race(Vehicle otherVehicle) {
            otherVehicle.race(this);
        }
    
        public Vehicle race(Helicopter heli) {
            return heli;
        }
        ...
    }
    
    
    public static void Main(string args[]) {
        Vehicle car = new Car();
        Vehicle helicopter = new Helicopter();
    
        Vehicle winner = helicopter.race(car);
        // returns helicopter
    }
    

    【讨论】:

    • 太棒了 - 谢谢@Johnbot (+1)!虽然这不违反lispkov替换吗?或者任何原则表明父类不应该知道它的孩子?打架?
    • 不干净,这是肯定的。您可以在车辆上使用 Race 类和 IComparable 接口以获得更多抽象。
    • 再次感谢@Johnbot (+1) - 你介意为这个想法发布一些快速的伪代码(Race/IComparable)吗?我很难想象它。再次感谢!
    • @TicketMonster Implementing equals with subclassing (down at #4) 是关于 LSPrinciple 的类似问题。您还必须检查是否需要对称(a.race(b) == b.race(a))、传递(a > b、b > c == a > c)等。根据您的算法,您不能让它像@987654323 @纸牌游戏,您只比较Vehicle定义的属性?这将摆脱对该接口其他实现的依赖。
    猜你喜欢
    • 1970-01-01
    • 2012-12-26
    • 2021-02-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多