Say I have a Car abstract class:
public abstract class Car {
public enum Feature {
FAST, SEXY, RELIABLE, FUEL_EFFICIENT
};
public static List<Feature> getFeatures() {
return new ArrayList<Car.Feature>();
}
public abstract int getMaxSpeed();
}
and a number of Car implementations with various constructors like these two:
public class CarA extends Car {
private static List<Feature> features = Arrays.asList(new Feature[] {
Feature.FAST, Feature.SEXY });
private int maxSpeed;
public CarA(int year) {
maxSpeed = year > 2000 ? 240 : 220;
}
public static List<Feature> getFeatures() {
return features;
}
@Override
public int getMaxSpeed() {
return maxSpeed;
}
}
and
public class CarB extends Car {
private static List<Feature> features = Arrays
.asList(new Feature[] { Feature.FAST });
private int maxSpeed;
public CarB(int year, int modelNumber) {
if (modelNumber > 10) {
maxSpeed = year > 2010 ? 180 : 160;
} else {
maxSpeed = 100;
}
}
public static List<Feature> getFeatures() {
return features;
}
@Override
public int getMaxSpeed() {
return maxSpeed;
}
}
I want to write a car class factory that suggests a number of car instances with various configurations depending on the taste of a person:
public class CarFactory {
public static class UserPreferences {
public List<Feature> requiredFeatures;
public int minimumSpeed;
}
public List<Car> getMatchingCars(int year, UserPreferences preferences) {
List<Class<?>> candidateCarClasses = Arrays.asList(new Class<?>[] {
CarA.class, CarB.class });
List<Class<?>> carClassesWithIncorrectFeatures = new ArrayList<Class<?>>();
for (Class<?> candidateClass : candidateCarClasses) {
Class<Car> carClass = (Class<Car>) candidateClass;
// XXX how do I check carClass.getFeatures() are included in
// requiredFeatures? carClass.getMethod("getFeatures",null)???
}
candidateCarClasses.removeAll(carClassesWithIncorrectFeatures);
List<Car> cars = new ArrayList<Car>;
for (Class<?> candidateClass : candidateCarClasses) {
if (CarA.class.equals(candidateClass.getClass())) {
CarA carA = new CarA(year);
// the rest is easy...
} else if (...) {
// the rest is easy...
}
}
return cars;
}
}
My question is:
how do I access the static methods of the various car classes without having to instantiate any car object at location XXX in my code?
And if that can't be done or if I am not approaching this properly, what would be the right way to solve my problem? I.e. how can my car factory trim out first all the classes that do not have the correct features before having to instantiate the candidate classes that are left. (In the real situation I am contemplating, I have many object instances to consider for each class and the constructors are resource intensive.)
Obviously, I could move the features supported by each car implementation outside of the classes into a separate map, but it seems a cleaner approach to have all info related to a specific car instance in that implementation rather that split across multiple locations.