Java 代表链是否合适

Java 代表链是否合适,java,algorithm,design-patterns,recursion,Java,Algorithm,Design Patterns,Recursion,在一次采访中,我被要求执行一项商业规则 需求变化。他们总是这样做: 如果金额低于100000美元,则评估20%的费用。 10万美元到50万美元之间的任何金额都要缴纳10%的费用。 如果金额超过500000美元,则评估5%的费用 计算任意金额x的费用 示例:如果发票金额为600000美元,则费用应为65000美元 如果发票金额为50000美元,则费用应为10000美元 如果发票金额为200000美元,则费用应为30000美元 我使用CofR,但面试官接着问,如果他们的条件超过3个,比如n个条件,我

在一次采访中,我被要求执行一项商业规则

需求变化。他们总是这样做:

如果金额低于100000美元,则评估20%的费用。 10万美元到50万美元之间的任何金额都要缴纳10%的费用。 如果金额超过500000美元,则评估5%的费用 计算任意金额x的费用

示例:如果发票金额为600000美元,则费用应为65000美元

如果发票金额为50000美元,则费用应为10000美元

如果发票金额为200000美元,则费用应为30000美元

我使用CofR,但面试官接着问,如果他们的条件超过3个,比如n个条件,我会创建n个类来处理每个请求吗


他们是否是解决问题的更好方法?旁白:为每个条件编写一个很长的递归函数检查。

我猜面试官的意思是,对于这样的问题,责任链模式可能有点设计过度。还有一种观点认为,您的实现类实际上也有同样的责任,因为它们都是基于给定的输入计算数量,只是使用不同的参数

我可能会用两个简单的类来实现这一点。我们将根据输入值计算百分比费率,并使用此费率返回费用金额

如果需要添加第四个条件,只需将其添加到包含速率计算的类中即可。对于这样一个简单的问题,我不明白为什么需要比这更复杂

编辑:

我的想法与@chrylis相同,因为有一个类通过处理一个有序的速率列表来执行计算

class Rate {
    int rangeSize;
    double commission;

    Rate(int rangeSize, double commission){
        this.rangeSize = rangeSize;
        this.commission = commission;
    }

    int computeForAmount(int amount) {
        if (amount <= 0) {
            return 0;
        }
        return (int) (Math.min(amount, this.rangeSize) * this.commission);
    }
}

class FeeCalculator {

    List<Rate> rates = Arrays.asList(
            new Rate(100, 0.2),
            new Rate(400, 0.1),
            new Rate(500, 0.05));

    int calculateCommission(int startingAmount) {
        int commission = 0;
        int remainingAmount = startingAmount;

        for (Rate rate : this.rates) {
            commission += rate.computeForAmount(remainingAmount);
            remainingAmount -= rate.rangeSize;
        }

        return commission;
    }

}

我承认,我并不完全乐意通过调用rate.rangeSize来打破封装,但它确实展示了我试图表达的设计。

我猜面试官是在暗示,对于这样的问题,责任链模式可能有点设计过度。还有一种观点认为,您的实现类实际上也有同样的责任,因为它们都是基于给定的输入计算数量,只是使用不同的参数

我可能会用两个简单的类来实现这一点。我们将根据输入值计算百分比费率,并使用此费率返回费用金额

如果需要添加第四个条件,只需将其添加到包含速率计算的类中即可。对于这样一个简单的问题,我不明白为什么需要比这更复杂

编辑:

我的想法与@chrylis相同,因为有一个类通过处理一个有序的速率列表来执行计算

class Rate {
    int rangeSize;
    double commission;

    Rate(int rangeSize, double commission){
        this.rangeSize = rangeSize;
        this.commission = commission;
    }

    int computeForAmount(int amount) {
        if (amount <= 0) {
            return 0;
        }
        return (int) (Math.min(amount, this.rangeSize) * this.commission);
    }
}

class FeeCalculator {

    List<Rate> rates = Arrays.asList(
            new Rate(100, 0.2),
            new Rate(400, 0.1),
            new Rate(500, 0.05));

    int calculateCommission(int startingAmount) {
        int commission = 0;
        int remainingAmount = startingAmount;

        for (Rate rate : this.rates) {
            commission += rate.computeForAmount(remainingAmount);
            remainingAmount -= rate.rangeSize;
        }

        return commission;
    }

}

我承认,我并不完全乐意通过调用rate.rangeSize来打破封装,但它确实展示了我试图阐明的设计。

我认为在这种情况下,一个简单的策略模式就足够了。比如:

interface FeeAssessor {
    public double assessFee(double invoice);
}

FeeAssessor feeAssessor = new FeeAssessor() {
        // logic goes here
    };

double calculateFee(double invoice) {
    return feeAssessor.assessFee(invoice);
}

对于您介绍的简单业务逻辑,我认为在一个函数中实现它会更简单。您可以实现不同的简单策略,并根据需要交换策略对象。如果费用评估算法依赖于多个相互独立的可变因素,那么您可以进一步将它们划分为多个策略方法。

我认为在这种情况下,简单的策略模式就足够了。比如:

interface FeeAssessor {
    public double assessFee(double invoice);
}

FeeAssessor feeAssessor = new FeeAssessor() {
        // logic goes here
    };

double calculateFee(double invoice) {
    return feeAssessor.assessFee(invoice);
}

对于您介绍的简单业务逻辑,我认为在一个函数中实现它会更简单。您可以实现不同的简单策略,并根据需要交换策略对象。如果费用评估算法依赖于多个相互独立的可变因素,则您可以进一步将其拆分为多个策略方法。

CoR在链成员具有实质性不同规则时很有用,但在这种情况下,如果金额超过X,所有规则基本上都是相同的,收取一定百分比的费用。与独立类不同,只需使用一个类似结构的类来保存最小金额和百分比,并使用另一个类来查找适当的费用:

class FeeSchedule {
    static class Entry implements Comparable<Entry> {
        int threshold;
        int percentage;

        int compareTo(Entry other) {
            // sort by percentage, descending
        }

    SortedSet<Entry> feeTable;

    int calculateFee(int invoiceAmount) {
        for(Entry e : feeTable)
            if(invoiceAmount > e.threshold)
                return (invoiceAmount * e.percentage);

        // error condition; return 0?
    }
}

当链的成员具有实质上不同的规则时,CoR是有帮助的,但在这种情况下,所有规则基本上是相同的,如果金额超过X,则收取一定百分比的费用。与独立类不同的是,只有一个类似结构的类持有最小金额和百分比,另一个是查找适当费用的:

class FeeSchedule {
    static class Entry implements Comparable<Entry> {
        int threshold;
        int percentage;

        int compareTo(Entry other) {
            // sort by percentage, descending
        }

    SortedSet<Entry> feeTable;

    int calculateFee(int invoiceAmount) {
        for(Entry e : feeTable)
            if(invoiceAmount > e.threshold)
                return (invoiceAmount * e.percentage);

        // error condition; return 0?
    }
}

你能用伪代码或者别的什么把你的解释写下来吗?我似乎不明白你提出的逻辑。谢谢。我明白了,这完全消除了我的递归,使它更面向对象,而不是过程@克丽利斯的观点现在更清楚了。谢谢你,伙计。袋子里新添的东西。你能把你的解释写在一张纸上吗
seudocode之类的,我似乎不明白你提出的逻辑。谢谢。我明白了,这完全消除了我的递归,使它更面向对象,而不是过程@克丽利斯的观点现在更清楚了。谢谢你,伙计。新添加到包中。你在这里得到了很棒的逻辑,但是我如何获得每个条目的百分比呢。我似乎无法就此得出结论。@Ayodeji这是一个基本的草图。getter、constructor等等。这里有非常棒的逻辑,但是我如何获得每个条目的百分比呢。我似乎无法就此得出结论。@Ayodeji这是一个基本的草图。getter、构造函数等。