【问题标题】:Use Generics <K> to reduce duplicate code?使用泛型 <K> 减少重复代码?
【发布时间】:2018-02-20 05:54:28
【问题描述】:

我有以下代码。如您所见,我正在执行类似的逻辑,但一次用于自行车,一次用于汽车。我可以使用&lt;K&gt; 来减少重复的代码吗?我没有使用过&lt;K&gt;,所以我不确定我可以在哪里以及如何准确地合并它。我在哪里可以决定是拨打getCarsWithFeature还是getBikesWithFeature

最好的做法是减少行数(可能会降低可读性)还是拥有类似重复的代码?

public Set<Car> getPremiumCars(String filter) {
    final Callable<Set<Car>> retryGetCars = new RetryingCallable<>(retryStrategy(), getCars(filter));  
    return retryGetCars.call();
}

public Callable<Set<Car>> getCars(String feature) {
    return new Callable<Set<Car>>() {
        @Override
        public Set<Car> call() throws Exception {
            Set<Car> cars = getCarsWithFeature(feature); 
            return Collections.unmodifiableSet(cars);
        }
    };
}

public Set<Bike> getPremiumBikes(String filter) {
    final Callable<Set<Bike>> retryGetBikes = new RetryingCallable<>(retryStrategy(), getBikes(filter));
    return retryGetBikes.call();            
}

public Callable<Set<Bike>> getBikes(String feature) {
    return new Callable<Set<Bike>>() {
        @Override
        public Set<Bike> call() throws Exception {
            Set<Bike> bikes = getBikesWithFeature(feature); 
            return Collections.unmodifiableSet(bikes);
        }
    };
}

【问题讨论】:

  • 是的,如果您有 Car 和 Bike 的通用(基类)类型,则可以
  • 您可能可以,但 Cars 和 Bikes 完全不同,我认为您会遇到泛型问题。将所有通用代码分解到一个抽象基类中可能会更好,因为这仍然允许您专门化 Bike 或 Car 子类所需的任何代码。
  • 这个问题的答案应该与getCarsWithFeaturegetBikesWithFeature 对应。是否使用泛型,它们似乎是必须进行的不同调用。
  • 谢谢@Piro。是的,它们确实是不同的电话。在这种情况下不能使用泛型吗?
  • 为什么代码中充斥着Callables和其他无关的东西?既然你在基础方面遇到问题,你应该坚持使用基本代码,而不是无缘无故地让它看起来“高级”。

标签: java oop generics inheritance


【解决方案1】:

我不知道你的全部代码,但我建议两个类都实现相同的接口 - 比如说Vehicle

  public interface Vehicle {
  }

然后你可以编写最近可以重用的代码:

  public <T extends Vehicle> Set<T> getPremiumVehicle(Function<String, Callable<Set<T>>> vehicleSupplier, String filter) throws Exception {
    final Callable<Set<T>> retryGetCars = new RetryingCallable<T>(retryStrategy(), vehicleSupplier.apply(filter));
    return retryGetCars.call();
  }

  public <T extends Vehicle> Callable<Set<T>> getVehicle(Function<String, Set<T>> vehicleSupplier, String feature) {
    return () -> {
      Set<T> vehicles = vehicleSupplier.apply(feature);
      return Collections.unmodifiableSet(vehicles);
    };
  }

现在,您可以重用上面的代码,例如:

  public Set<Car> getPremiumCars(String filter) throws Exception {
    return getPremiumVehicle(this::getCars, filter);
  }

  public Set<Bike> getPremiumBikes(String filter) throws Exception {
    return getPremiumVehicle(this::getBikes, filter);
  }

  public Callable<Set<Car>> getCars(String feature) {
    return getVehicle(this::getCarsWithFeature, feature);
  }

  public Callable<Set<Bike>> getBikes(String feature) {
    return getVehicle(this::getBikesWithFeature, feature);
  }

【讨论】:

    【解决方案2】:

    创建一个 Car 和 Bike 的基类,然后把通用方法放在那里。 然后从中扩展汽车和自行车。使用基类更新通用方法。下面给出了实现的示例提示:

    class Vehicle {
      public Set<Vehicle> getWithFilter(String filter) {
        final Callable<Set<Vehicle>> retryGet = new RetryingCallable<>(retryStrategy(), get(filter));
        return retryGet.call();            
      }
      public Callable<Set<Vehicle>> getWithFeature(String feature) {
        return new Callable<Set<Vehicle>>() {
            public Set<Vehicle> call() throws Exception {
                Set<Vehicle> vehicles = getWithFeature(feature); 
                return Collections.unmodifiableSet(vehicles);
            }
        };
      }
    
    } 
    class Car extends Vehicle {
    }
    class Bike extends Vehicle {
    }
    

    现在调用使用:

    Car car = new Car();
    car.getWithFilter(/* Pass parameter*/);
    
    Bike bike = new Bike();
    bike.getWithFilter(/* Pass parameter*/);
    

    【讨论】:

    • 感谢您的回答。正如@Piro 在上面的 cmets 中提到的,有 2 个不同的调用 getCarsWithFeaturegetBikesWithFeature。即使有一个基类,那部分代码仍然必须存在。你认为我可以移到基类的哪一部分?
    • 感谢您的回答。我会试一试。但是,如果我有完全不相关的课程而不是汽车和自行车呢?在那种情况下,我不能有一个基类。在这种情况下会有什么建议?
    • 在这种情况下,您必须使用通用模板或使用 Java Object 类,然后转换为适当的类。
    • 是的,这也是我的想法。所以我的问题是关于泛型的。我不能使用基类方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-12
    • 1970-01-01
    • 2012-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多