这就是我所说的:
import java.util.Arrays;
import java.util.List;
enum Material {
CARDBOARD, ALUMINIUM, PLASTIC
}
class BoxProperties {
public Material material;
public double length;
}
abstract interface RuleSet {
public boolean isSatisfiedBy(BoxProperties props);
}
class MyRuleSet implements RuleSet {
private final Material material;
private final double[] length;
public MyRuleSet(Material mat, double minLength, double maxLength) {
this.material = mat;
this.length = new double[] {minLength, maxLength};
}
@Override
public boolean isSatisfiedBy(BoxProperties props) {
if (props.material != material) return false;
if (props.length < length[0] || props.length > length[1]) return false;
return true;
}
}
public class Box {
private static final List<? extends RuleSet> rules;
public final Material material;
public final double length;
private Box(BoxProperties props) {
this.material = props.material;
this.length = props.length;
}
public static Box createBox(BoxProperties props)
throws IllegalArgumentException {
for (RuleSet rs : rules) {
if (rs.isSatisfiedBy(props)) {
return new Box(props);
}
}
//XXX This should probably be made a checked exception
throw new IllegalArgumentException(
"No supported box type can fullfil the requests");
}
static {
rules = Arrays.asList(
new MyRuleSet(Material.CARDBOARD, 15, 30),
new MyRuleSet(Material.ALUMINIUM, 30, Double.POSITIVE_INFINITY),
new MyRuleSet(Material.PLASTIC, 0, 100)
);
}
}
如果您确定需要不同的Box
子类,那么您可以Box
抽象化,并在接口中添加一个createBox
方法,RuleSet
实现该方法以返回自定义实现。此外,您可能需要向 Box 构造函数传递一些额外的参数,该参数不在请求中,因此您可能需要添加它。
无论如何,我再说一遍,我认为你不应该子类化,因为客户端类仍然会看到Box
. 为了确定它是否可以被包装,它应该像这样
if (returnedBox instanceof MaybeWrappableBox && ((MaybeWrappableBox)returnedBox).isWrappable()) {
...
}
然后,您最好添加isWrappable()
到所有盒子中,如果盒子永远不可包装,则返回 false。这将简化调用者代码,而不是特别复杂的被调用者代码。