1

我在一次采访中被要求实施一项业务规则

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

  1. 对低于 100,000 美元的任何金额征收 20% 的费用。
  2. 对 100,000 美元至 500,000 美元之间的任何金额征收 10% 的费用。
  3. 对超过 500,000 美元的任何金额征收 5% 的费用

计算任意金额 x 的费用。

示例:给定一张 600,000 美元的发票,费用应为 65,000 美元。

给定一张 50,000 美元的发票,费用应为 10,000 美元。

给定一张 200,000 美元的发票,费用应为 30,000 美元。

我使用了 CofR,但面试官随后问如果他们的条件超过 3 个,比如其中的 n 个,我会创建 n 个类来处理每个请求。

除了为每个条件编写一个非常长的递归函数检查之外,他们是否是解决问题的更好方法。

4

3 回答 3

2

我猜面试官是在暗示像责任链模式这样的东西对于这样的问题会有点过度设计。还有一个论点是您的实现类实际上将具有相同的责任,因为它们都将根据给定的输入计算一个数量,只是使用不同的参数。

我可能会用两个简单的类来做到这一点。可以根据输入值计算百分比费率,然后使用该费率返回费用金额。

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

编辑:

我的想法与@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但它确实展示了我试图表达的设计。

于 2013-10-07T23:08:03.373 回答
2

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?
    }
}
于 2013-10-07T23:22:02.000 回答
0

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

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

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

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

assessFee()对于您提出的一个简单的业务逻辑,我认为在一个函数中实现它会更简单。您可以实现不同的(简单)对象并根据需要换出“策略”对象。如果费用评估算法取决于多个相互独立的不同因素,那么您可以进一步将它们拆分为多种策略方法。

于 2013-10-07T23:20:43.427 回答