假设我正在构建一个通用的AssemblyLine
类,该类可以接收物理对象,对其进行测量,将其放入纸板箱中并进行礼品包装。我希望用户能够提供自己的对象测量策略(也许有些关心总体积,有些只是关心对象的最长尺寸)以及他们自己的盒子选择策略(因为用户会最了解哪种纸板)他们要使用的盒子)。
如果AssemblyLine
可以接受对物理对象的超类进行操作的测量策略和选择框策略,那就太好了。毕竟,如果用户有一种适用于所有Dessert
的测量策略,我们应该让他们在AssemblyLine<Cake>
和AssemblyLine<Pie>
中使用相同的策略,对吗?
因此,让我们从测量策略开始:
public interface PhysicalObjectMeasurementStrategy<T> {
Measurement measureObject(T object);
}
很简单,我认为没有争议。接下来,我们要为包装盒选择策略定义一个接口。这可能是我的第一个错误,但现在让我们开始吧:
public interface CardboardBoxSelectionStrategy<T> {
CardboardBoxSize chooseCardboardSizeForObject(T object, PhysicalObjectMeasurementStrategy<? super T> measurementStrategy);
}
我的想法是,我希望能够为我们可以测量的任何东西选择一个盒子。如果我们有一个用于馅饼的盒子选择策略和一个可以处理任何甜点的度量策略,那么能够在多个地方使用甜点度量策略将是一件很不错的事情。
现在,将它们整合到装配线中:
public class AssemblyLine<T> {
private final PhysicalObjectMeasurementStrategy<? super T> measurementStrategy;
private final CardboardBoxSelectionStrategy<? super T> boxSelectionStrategy;
// ...
public void giftWrapObject(final T physicalObject) {
// Here's where things fall apart:
boxSelectionStrategy.chooseCardboardSizeForObject(physicalObject, this.measurementStrategy);
// ...
}
}
据我所知(这个问题可能是完全错误的!),这个问题是,我们没有任何方法可以保证
measurementStrategy
和boxSelectionStrategy
都引用了T
的同一个超类,并且实际上可能是在引用无关的超类(或接口)。例如,我们可能遇到以下情况:PhysicalObjectMeasurementStrategy<Cylindrical>
CardboardBoxSelectionStrategy<Edible>
AssemblyLine<Cake>
两种策略都适用于组装线,但是因为并非所有的
Cylindrical
对象都是Edible
(反之亦然),所以将测量策略传递给盒子选择策略没有意义。因此,直截了当:在声明或构造
AssemblyLine
时,是否有一种很好的方法来确保我们在谈论相同的或至少兼容的超类?如果不是,是否有解决该问题的另一种好方法(这个问题有名字吗?),还是我需要重新考虑设计并可能在装配线中使用不太灵活的组件?谢谢!
最佳答案
一种方法是对兼容的度量和框选择策略使用单独的类型参数:
class AssemblyLine<M, B extends M> {
private final PhysicalObjectMeasurementStrategy<M> measurementStrategy;
private final CardboardBoxSelectionStrategy<B> boxSelectionStrategy;
public void giftWrapObject(B physicalObject) {...
另一种方法可能是允许将任何可以测量对象的测量策略传递给盒子选择策略:
<R extends T> CardboardBoxSize chooseCardboardSizeForObject(R object,
PhysicalObjectMeasurementStrategy<? super R> measurementStrategy);
或者,您可以先测量对象,然后将测量结果传递给框选择策略。
我不知道这个问题的名字。