0

我对 Java 比较陌生,正在努力解决一个问题。我有一个基类,对于这个例子,我们称它为一个盒子,我还有 3 个盒子类继承了基本盒子类。原因是这 3 个盒子中的每一个都具有不同的特征,从而使它们彼此区分开来。让我们假设:Box01 只能用纸板制成,长度在 15 到 30 厘米之间。Box02 只能由铝制成,长度大于 30 厘米。box03 只能由塑料制成,长度小于 100 厘米。

在所讨论的程序中,用户不能具体选择盒子的类型,而是必须提供他们的要求,并且程序必须回应说产品是否可能。所以 120cm 的塑料盒是不可能的,50xm 的纸板箱也不可能。

我目前的解决方案是使用 if 语句,例如:

if(boxType == 'cardboard' && length >= 15 && length <= 30){
    Box = new box01(boxType, length);
else if(boxType == 'aluminium' && length >= 30){
    Box = new box02(boxType, length);
}

我知道在这个简化的示例中,似乎没有必要拥有额外的盒子类,但假设在真实版本中盒子有更多独特的特征,这些特征将反映在类属性和构造函数中。

现在我的问题。这种特殊的方法在这里看起来不错,只有 2 个测试和几个 if,但我的程序有更多的属性和更多的测试。除了 ifs 之外,我的程序是否还有另一种更复杂的方法来检测我的程序应该制作什么样的盒子。

感谢任何花时间阅读、理解并发表回复的人。我确信解决方案比我想象的要简单得多。

4

2 回答 2

0

这就是我所说的:

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。这将简化调用者代码,而不是特别复杂的被调用者代码。

于 2013-11-11T23:51:59.937 回答
0

一个好的方法是像这样构建您的应用程序:

  1. 对 de 使用具有基本实现的接口或抽象类:

    public interface BoxType(){ //Or BoxFactory or smth like that
    
        public boolean isApplicable(int userInput1, String userInput2...);        /// If you have more than 1-2 user input elements, create a special object (something like `UserInput`) with the user input/requirements and just pass it.
    
        public Box buildBox(int userInput1, String userInput2...);
        ...
    }
    
  2. 实现每个盒子类型,在方法中定义它的适用条件isApplicable()以及如何在方法中构建它buildBox()

  3. 无论您需要检查哪种盒子类型,只需循环浏览现有(注册的)盒子类型并检查哪个适用并构建它。
于 2013-11-11T23:24:20.843 回答