0

私はJavaに比較的慣れておらず、問題を克服しようとしています..私は基本クラスを持っています。この例ではそれをボックスと呼び、基本ボックスクラスを継承する3つのボックスクラスがあります。その理由は、これら 3 つのボックスのそれぞれが、互いに異なる特性を持っているためです。Box01 は厚紙でのみ作成でき、長さは 15 ~ 30 cm です。Box02 はアルミニウム製で、長さが 30cm を超えるものに限ります。box03 はプラスチックのみで、長さは 100cm 未満です。

問題のプログラムでは、ユーザーはボックスのタイプを具体的に選択することはできませんが、代わりに要件を提供する必要があり、プログラムは製品が可能かどうかを応答する必要があります。そのため、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 のみで問題ないように見えますが、私のプログラムにはかなり多くの属性とさらに多くのテストがあります。私のプログラムがif以外にどのような種類のボックスを作成する必要があるかを私のプログラムが検出する別のより洗練された方法はありますか?

時間を割いてこれを読み、理解し、返信を投稿してくれた人に感謝します。解決策は、私が考えているよりもはるかに簡単だと確信しています。

4

2 に答える 2

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 に答える
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追加できます。また、リクエストに含まれていない追加のパラメーターを Box コンストラクターに渡す必要がある場合があるため、それを追加することをお勧めします。createBoxRuleSet

とにかく、繰り返しますが、サブクラス化する必要はないと思います。クライアント クラスにはBox. ラップできるかどうかを判断するには、次のようにする必要があります

if (returnedBox instanceof MaybeWrappableBox && ((MaybeWrappableBox)returnedBox).isWrappable()) {
    ...
}

次に、isWrappable()すべてのボックスに追加し、ボックスがラップできない場合は false を返すことをお勧めします。これにより、呼び出し元のコードが簡素化されますが、呼び出し先のコードが特に複雑になることはありません。

于 2013-11-11T23:51:59.937 に答える