23

我从来没有见过一种很好地做到这一点的方法,我很想看看其他人是如何做到的。目前我像这样格式化它:

public Booking createVehicleBooking(Long officeId, 
                                    Long start, 
                                    Long end,
                                    String origin, 
                                    String destination, 
                                    String purpose,         
                                    String requirements, 
                                    Integer numberOfPassengers) throws ServiceException {
/*..Code..*/
}
4

6 回答 6

16

像这样的大量参数通常(但不总是)指示您可以使用对象来表示参数集。在以下情况下尤其如此:

  • 有几种方法具有相似的大参数集,可以用带参数对象的单个方法替换。

  • 该方法被称为create...

所以你上面的代码可能会变成(请原谅我的 C++,我是 Java 开发人员):

class BuildVehicleBooking {
    Long officeId;
    Long start;
    Long end;
    String origin;
    String destination;
    String purpose;             
    String requirements;
    Integer numberOfPassengers;

    Booking createVehicleBooking () throws ServiceException { ... }
}

这是建造者模式。这种模式的优点是您可以分段构建一组复杂的参数,包括参数如何相互关联的多种变体,甚至在新信息可用时覆盖参数,然后最终调用该create方法。

另一个潜在的优势是您可以添加一个verifyParameters方法来检查它们的一致性,然后再到达creating最终对象。这适用于创建对象涉及不可逆步骤的情况,例如写入文件或数据库。

请注意,与所有模式一样,这并不适用于所有情况,也可能不适用于您的情况。如果您的代码足够简单,那么这种模式可能会过度设计它。如果代码变得混乱,重构为这种模式可能是简化它的好方法。

于 2008-10-10T01:35:09.037 回答
11
public Booking createVehicleBooking(
    Long officeId, 
    Long start, 
    Long end,
    String origin, 
    String destination, 
    String purpose,                 
    String requirements, 
    Integer numberOfPassengers)

throws ServiceException {
/*..Code..*/
}
于 2008-10-10T01:16:47.013 回答
3

我倾向于用几个对象而不是一个对象来解决这个问题。

所以它变成

public Booking createVehicleBooking(Long officeId, DateRange dates, TripDetails trip)

而 DateRange 和 Trip 详细信息仅包含数据的相关部分。虽然可以说 dateRange 可能是行程的一部分,而 Requirements 和 Number of Passengers 可以从 TripDetails 中删除并成为请求的一部分。

事实上,有几种方法可以对数据进行切分,但我不得不说将您的大列表分成相关参数组并为它们构建一个对象将允许更清晰的编程风格并增加可能的重用。

请记住,始终可以将对象嵌入对象中,从而使您拥有

public Booking createVehicleBooking(BookingParameters parameters)

而 BookingParameters 包含 TripDetails 和 DateRange 对象以及其他参数。

于 2008-10-10T02:49:04.130 回答
2

在调用端,我喜欢使用如下注释来模拟命名参数:

booking.createVehicleBooking(
    getOfficeId(),      // Long officeId 
    startVariable,      // Long start 
    42,                 // Long end
    getOrigin(),        // String origin 
    "destination",      // String destination 
    "purpose",          // String purpose       
    "requirements",     // String requirements
    3                   // Integer numberOfPassengers
);
于 2015-05-12T22:00:05.850 回答
2

Google Java Style Guide没有直接解决这个问题,但我同意他们在 Guava 中的格式化方式,即

com.google.common.collect.Collections2.transform

public static <F, T> Collection<T> transform(
    Collection<F> fromCollection, Function<? super F, T> function) {
  return new TransformedCollection<>(fromCollection, function);
}

com.google.common.collect.ImmutableRangeMap.toImmutableRangeMap

public static <T, K extends Comparable<? super K>, V>
    Collector<T, ?, ImmutableRangeMap<K, V>> toImmutableRangeMap(
        Function<? super T, Range<K>> keyFunction,
        Function<? super T, ? extends V> valueFunction) {
  return CollectCollectors.toImmutableRangeMap(keyFunction, valueFunction);
}

我认为规则是:

  • (如果可能,尽量保持在一条线上)
  • 在方法名称和大括号之后中断
  • 将参数缩进一级以将它们与正文区分开来

就个人而言,如果我必须打破,我更喜欢在每个参数之后打破,即

public static Foo makeFoo(
    Foo foo,
    Bar bar,
    Baz baz)
      throws FooException {
  f();
}
于 2017-09-18T08:54:38.867 回答
1

我喜欢您展示的每行一个参数的方法。我发现很容易目视扫描它并查看存在的内容。

我发现当人们使用像 Guice 这样的东西时,你通常会得到大量的参数,这使得它更容易阅读。

于 2016-07-24T00:48:01.713 回答