これは私が話していたことです:
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
追加できます。また、リクエストに含まれていない追加のパラメーターを Box コンストラクターに渡す必要がある場合があるため、それを追加することをお勧めします。createBox
RuleSet
とにかく、繰り返しますが、サブクラス化する必要はないと思います。クライアント クラスにはBox
. ラップできるかどうかを判断するには、次のようにする必要があります
if (returnedBox instanceof MaybeWrappableBox && ((MaybeWrappableBox)returnedBox).isWrappable()) {
...
}
次に、isWrappable()
すべてのボックスに追加し、ボックスがラップできない場合は false を返すことをお勧めします。これにより、呼び出し元のコードが簡素化されますが、呼び出し先のコードが特に複雑になることはありません。