在运行时

时间:2016-06-02 06:33:38

标签: java abstract-class

我有以下基类和派生类:

public abstract class Drone {
    public void Drone(){}
    public abstract boolean commonFunc();
}

public class DroneMain extends Drone {
    @Override
    public boolean commonFunc(){
        return false;
    }

    public boolean droneMainFunc(){
        return true;
    }
}

public class DroneOther extends Drone {
    @Override
    public boolean commonFunc(){
        return true;
    }

    public boolean droneOtherFunc(){
        return false;
    }
}

public class DroneMgr {
    public enum DroneType {MAIN, OTHER}

    public Drone getDrone(DroneType type){
        if (type.equals(DroneType.MAIN))
            return new DroneMain();
        else
            return new DroneOther();
    }
}

调用这些类的代码如下:

private DroneManager droneManager;
private Drone drone;

droneManager = new DroneManager();
drone = droneManager.getDrone(DroneManager.DroneType.MAIN);
boolean value = drone.droneMainFunc();

我的问题涉及以下几行:

drone = droneManager.getDrone(DroneManager.DroneType.MAIN);
boolean value = drone.droneMainFunc();

如何制作它以便我可以从无人机对象调用droneMainFunc()?

否则,如果我在运行时之前不知道它的类型,我该怎么做呢。 如果我不能使用Drone(无人机实例),那么直到运行时我才会知道,我将不得不创建一个DroneMain对象和一个DroneOther对象,然后根据返回的类型分配/转换一个。我想避免这种情况,因为我确信有更好的模式。

2 个答案:

答案 0 :(得分:0)

最简单的方法是使用instanceof运算符。

drone = droneManager.getDrone(DroneManager.DroneType.MAIN);
if (drone instanceof DroneMain) {
    ((DroneMain)drone).droneMainFunc();
} ...

但我会考虑在你的Drone类中包含另一个抽象方法,它只会调用正确的函数。这是因为你似乎想在它的实际类上独立执行一个函数。如果是这样,你应该在抽象类中包含另一个常用函数,两个实现都可以使用它们作为Drone#commonFunc

public abstract class Drone {
   public void Drone(){}
   public abstract boolean commonFunc();
   public abstract boolean doSomething();
}

public class DroneMain extends Drone {
   @Override
   public boolean commonFunc(){
       return false;
   }

   @Override
   public boolean doSomething() {
       return droneMainFunc();
   }

   public boolean droneMainFunc(){
       return true;
   }
}

public class DroneOther extends Drone {
   @Override
   public boolean commonFunc(){
       return true;
   }

   @Override
   public boolean doSomething() {
       return droneOtherFunc();
   }

   public boolean droneOtherFunc(){
       return false;
   }
}

...

boolean value = drone.doSomething();

答案 1 :(得分:0)

我有两个选择:

跳过枚举并改用类和泛型。这允许您在 DroneMgr 中对类型进行断言,并返回正确的类型。

public class DroneMgr {
    public <T extends Drone> T getDrone(Class<T> type) {
        if(DroneMain.class.equals(type)) {
            // Need to cast to T, but we already know that T is DroneMain
            return (T) new DroneMain();
        } else if (DroneOther.class.equals(type)) {
            return (T) new DroneOther();
        } else {
            throw new IllegalArgumentException("Unknown Drone class " + type);
        }
    }
}

使用:

DroneMain drone = droneManager.getDrone(DroneMain.class); // No need to cast
boolean value = drone.droneMainFunc();

另一个选择是使用策略模式并直接在枚举中实现功能,这样可以轻松添加新类型。

public enum DroneType {
    MAIN {
        @Override
        public boolean handle() {
            return new DroneMain().droneMainFunc();
        }
    },
    OTHER {
        @Override
        public boolean handle() {
            return new DroneMain().droneOtherFunc();
        }
    };

    public abstract boolean handle();
}

然后你就做了:

boolean value = DroneType.MAIN.handle();

如果您不是在枚举中编写实现的粉丝,您可以将功能分解为单独的类,这些类都实现了一个公共接口,并且只是在枚举中引用该实例。

public interface DroneHandler {
    boolean handle();
}

public class DroneMainHandler implements DroneHandler {
    @Override
    public boolean handle() {
        return new DroneMain().droneMainFunc();
    }
}

public class DroneOtherHandler implements DroneHandler {
    @Override
    public boolean handle() {
        return new DroneOther().droneMainFunc();
    }
}

public enum DroneType {
    MAIN(new DroneMainHandler()),
    OTHER(new DroneOtherHandler());

    public final DroneHandler handler;

    private DroneType(final DroneHandler handler) {
        this.handler = handler;
    }
}

用法然后变为:

boolean value = DroneType.MAIN.handler.handle();