4

設計上の決定を下す必要があるケースに遭遇しました (プログラム自体についてではなく、その状況で他の人が何をしているのかを知るために、これを API であるかのように見るのが最善です) )。私は列挙型クラスを持っています:

public enum Type
{

    CAPTAIN(2),  // Only Use CalcMorale never other
    LEADER(5),   // Only use CalcMorale never other
    PARTIER(80); // Only use CalcMorale2 never other

    int calcMorale(int inMorale)
    {
        return inMorale * (100 + morale) / 100;
    }

    int calcMorale2(int inMorale, int teamCount)
    {
        return inMorale + morale * teamCount;
    }

    int morale;

    private Type(int aMor)
    {
        morale = aMor;
    }

}

これらの列挙型の 1 つを保持し、パラメーターを渡すクラスでもある Character があります。

コメントされている問題は、特定の列挙型のみが列挙型クラス内で特定のメソッドを使用するようにしたいということです。リーダーはチームの士気に 5% を追加しますが、パーティーはそのパーティー内のメンバーごとに 80 を追加するため、別のパラメーターが必要になります。いくつかの方法で問題を解決できますが、コミュニティがどのように対処するかについての一般的なコンセンサスを知りたいです。

私はできた:

適切なメソッドを呼び出すのはプログラマーの責任にしてください。(これは私には間違っているように聞こえます)。

各列挙型に独自のバージョンの関数を与えます。(これは巨大なファイルを作成し、大量のコードを繰り返すことになります)。

これを処理するスイッチを持つメソッドを持つ 'Character' クラスに責任を残します。(これは、プログラマが意図せずに計算を変更できることを意味します)。ただし、後で代わりに列挙型をファイルに移動したい場合は、これにより問題が少なくなります。ただし、これが列挙型の責任のみである場合、これがカプセル化を破るかどうかは疑問です。

Type をクラスにし、匿名の内部クラスを介してメソッドを定義します。この場合、enum クラスに getByName() があるのではなく、クラスがマップに追加されます。

--

何が最も適切だと思いますか? (APIを使用しているかのように、クラスが可能な限り自己依存的であることを好みます(そうはなりません)。列挙型の量に応じて、あなたの提案はどのように/影響を受けますか?そして、私が望んでいたケースはどうですか?両方のメソッドを使用できる列挙型? 言語は Java です。

4

3 に答える 3

3

あなたが言ったように、アプリケーションがこれをどのように処理するかを考える必要があります。enum クラスでこれ自体を処理する場合は、ある種の条件とオーバーロードの形式が必要になります (つまり、開発者はいずれにせよ適切なメソッドを呼び出す責任があります。

ただし、開発者に関係なく常に teamcount を送信するように強制できます。

public enum Type {
    CAPTAIN(2),
    LEADER(5),
    PARTIER(80);

    private final int morale;

    private Type(int m){
        morale = m;
    }

    public int getMorale(int inMorale) {
         return getMorale (inMorale, 0);
    }

    public int getMorale(int inMorale, int teamCount) {
        switch (this) {
            case CAPTAIN:       
            case LEADER:
                return inMorale * (100 + morale) / 100;
            case PARTIER:
                return inMorale + morale * teamCount;
        }
        return 0;
    }
}

編集:スイッチを「これ」に変更

于 2013-05-14T13:55:55.690 に答える
1

複数のパラメータを Enum 値に渡して保存できます。

public enum Type
{

    CAPTAIN(2, true),  // Only Use CalcMorale never other
    LEADER(5, true),   // Only use CalcMorale never other
    PARTIER(80, false); // Only use CalcMorale2 never other
    ...

    int morale;
    boolean useFirstMethod;

    ...

    int calcMorale(int inMorale, int teamCount)
    {
        if (useFirstMethod) {
            return inMorale * (100 + morale) / 100;
        } else {
            return inMorale + morale * teamCount;
        }
    }

    ...
}
于 2013-05-14T13:50:31.287 に答える
1

適切なメソッドを呼び出すのはプログラマーの責任にしてください。(これは私には間違っているように聞こえます)。

そうです、それは最適な解決策ではありません。

各列挙型に独自のバージョンの関数を与えます。(これは大規模なファイルを作成し、多くのコードを繰り返すことになります)

これは、最初のオプションの拡張のように聞こえます。現在、呼び出し元は、n 個の値に対してどの n メソッドを呼び出すかを分類する責任がありenumます。

s ではなくenum、継承アプローチを検討してください。

メソッドcalcMoraleとメソッドcalcMorale2は非常に似ており、インターフェースで組み合わせることができます。

public interface Type
{
    int calcMorale(int inMorale);
}

このabstractクラスは、共通のcalcMorale機能を定義できます (必要に応じて他のクラスがオーバーライドします)。

public abstract class AbstractType
{
    protected final int morale;

    public AbstractType(int morale)
    {
        this.morale = morale;
    }

    int calcMorale(int inMorale)
    {
        return inMorale * (100 + morale) / 100;
    }
}

CaptainからLeader直接拡張しますAbstractType

public class Captain extends AbstractType
{
    public Captain()
    {
        super(2);
    }
}

public class Leader extends AbstractType
{
    public Leader()
    {
        super(5);
    }
}

ただし、メソッドはPartierオーバーライドされますcalcMorale(2 番目のパラメーターはコンストラクターの引数として渡されます)。

public class Partier extends AbstractType
{
    private final int teamCount;

    public Partier(int teamCount)
    {
        super(80);
        this.teamCount = teamCount;
    }

    @Override
    public int calcMorale(int inMorale)
    {
        return inMorale + morale * teamCount;
    }
}
于 2013-05-14T13:50:58.447 に答える