运行时期间的Java对象选择

时间:2013-11-11 23:06:39

标签: java

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

在有问题的程序中,用户无法专门选择框的类型,但也必须提供他们的要求,程序必须回答说产品是否可行。所以一个120厘米的塑料盒是不可能的,也不是50克的纸板盒。

我目前的解决方案是使用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个测试和几个ifs看起来不错,但我的程序有更多的属性和更多的测试。除了ifs之外,我的程序还有另一种更复杂的方法可以检测我的程序应该制作什么样的框。

感谢任何花时间阅读本文,理解并发布回复的人。我确信解决方案比我要做的更简单。

2 个答案:

答案 0 :(得分: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. 无论您需要检查哪种盒子类型,只需循环浏览现有(已注册)盒子类型并检查哪种类型适用并构建它。

答案 1 :(得分: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。这将简化调用者代码,同时不会使被调用者代码特别复杂。