首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >保险费计算器练习

保险费计算器练习
EN

Code Review用户
提问于 2017-09-16 16:43:30
回答 1查看 5.9K关注 0票数 2

在一次面试中,我尝试了一次编码练习,在这里定义和实现了(问题自述):

https://gitlab.com/vineet_康复中心/健康保险-保费-报价-发电机-2

它最初是一个简单的、单一的java类程序。

代码语言:javascript
复制
public double calculatePremium(Person person) {
    // Added base premium
    double premium = 5000;

    // Increase premium depending on age
    if (person.getAge() >= 18) {
        premium *= 1.1;
    }
    if (person.getAge() >= 25) {
        premium *= 1.1;
    }
    if (person.getAge() >= 30) {
        premium *= 1.1;
    }
    if (person.getAge() >= 35) {
        premium *= 1.1;
    }
    if (person.getAge() >= 40) {
        // Add 20% per 5 years above 40
        int age = person.getAge() - 40;
        while (age >= 5) {
            premium *= 1.2;
            age -= 5;
        }
    }

    // Add gender specific adjustments
    if (person.getGender() == Gender.MALE) {
        premium *= 1.02;
    }

    // Increase 1% per health issue
    for (HealthIssues issue : person.getHealthIssues()) {
        premium *= 1.01;
    }

    Set<Habbits> habbitsList = person.getHabbits();
    // Decrease 3% per good habbit
    for (Habbits habbit : habbitsList) {
        if (Constants.goodHabbits.contains(habbit)) {
            premium *= 0.97;
        }
    }
    // Increase 3% per good habbit
    for (Habbits habbit : habbitsList) {
        if (Constants.badHabbits.contains(habbit)) {
            premium *= 1.03;
        }
    }

    return premium;
}

最初我只有三个不同JUnits对象的Person对象。评审员提到,如果JUnit失败了,我们就不知道它到底在哪里失败了。

因此,我选择了各种计算方法,并给出了自己的方法。然后在我最初的calculatePremium()方法中调用它们。

代码语言:javascript
复制
public double calculatePremium(Person person) {
    // Added base premium
    double premium = 5000;
    premium = this.applyAgeBasedCalcs(person, premium);
    premium = this.applyGenderBasedCalcs(person, premium);
    premium = this.applyHealthIssuesBasedCalcs(person, premium);
    premium = this.applyGoodHabbitsBasedCalcs(person, premium);
    premium = this.applyBadHabbitsBasedCalcs(person, premium);
    return premium;
}

当然,还为它们添加了JUnits (不是一个详尽的集合)。因此,我们不只是为了最终的答案而测试,我们还在测试单个计算组件是否正常工作。

最后,审阅者提到,如果他曾经想要更改被调用的apply*方法的顺序或数量(添加新方法),但是不每次都更改这个类,我们将如何处理呢?他可能还想用这个原版的规则。我立即解释了策略模式&应请求执行它。

我只是创建了一个接口(PremiumCalculationStrategy) &目前实现它的一个类(NormalPremiumCalculationStrategy)。

代码语言:javascript
复制
public double calculatePremium(Person person) {
    // Added base premium
    double premium = 5000;
    premium = Rules.applyAgeBasedCalcs(person, premium);
    premium = Rules.applyGenderBasedCalcs(person, premium);
    premium = Rules.applyHealthIssuesBasedCalcs(person, premium);
    premium = Rules.applyGoodHabbitsBasedCalcs(person, premium);
    premium = Rules.applyBadHabbitsBasedCalcs(person, premium);
    return premium;
}

我使所有的apply*方法都是静态的,因为我没有看到实例化规则对象的必要性;没有状态&该方法是功能性的。

不幸的是,这一点没有得到很好的理解。他不喜欢静态的方法&说我破坏了所有的OO原则。他建议我应该使它更面向对象。此外,仅仅因为有一个类&接口,并不意味着它是一种策略模式。

我不太理解这些评论。有人能回顾一下这个&让我知道一个很好的编码方法吗?或者为什么我的实现如此糟糕?有什么好方法使它更面向对象,以及策略模式的正确用法是什么?

EN

回答 1

Code Review用户

回答已采纳

发布于 2017-09-17 20:01:48

一个良好的OOP设计是开放的扩展和封闭的修改。单方法实现与此相去甚远。

我认为这个练习的目的是能够从部件中构建一个高级计算器,这样您就可以轻松地修改可能发生变化的部分。这些零件是什么?

  • 基本保费
  • 基于条件的百分比修改器计算
    • 有一个条件列表,相关的百分比增加或减少。

百分比修饰符部分本质上是接受Person并返回百分比的函数。您可以提供这样的部件来简化计算机的构建,例如:

代码语言:javascript
复制
interface PremiumPercentCalculator extends Function<Person, Integer> {}

PremiumPercentCalculator male(int percent) {
    return person -> person.male ? percent : 0;
}

PremiumPercentCalculator preConditions(int percent) {
    return person -> person.preConditions().size() * percent;
}

PremiumPercentCalculator goodHabits(int percent) {
    return person -> person.habits().stream().filter(Habit::isGood).mapToInt(h -> percent).sum();
}

PremiumPercentCalculator badHabits(int percent) {
    return person -> person.habits().stream().filter(h -> !h.isGood()).mapToInt(h -> percent).sum();
}

然后,使用构建器模式,您可以从如下部分构建一个计算器:

代码语言:javascript
复制
float premium = new Calculator(person, 5000)
    .add(p -> getPremiumPercentByAge(p))
    .add(male(2))
    .add(preConditions(1))
    .add(badHabits(3))
    .add(goodHabits(-3))
    .calculate();

假设有一个用于保险代理的UI,他可以拖放与条件类型相对应的小部件,比如"is男性“、”预条件“等等,每个组件都有一个选项来修改要应用的百分比。这样的UI可以很容易地从我们提供的部件构建,并且可以通过添加更多的PremiumPercentCalculator实现来轻松地添加新的部件。

请注意,person和基本溢价5000是构造函数参数,因为它们对于计算器是绝对必要的,因此有必要预先要求它们,以便实现的其余部分无需进一步验证就可以存在。

您可能会注意到,badHabitsgoodHabits迭代了两次习惯集合。这很可能可以忽略不计。但是如果不是,那么通过添加另一个部分就可以很容易地修复:

代码语言:javascript
复制
PremiumPercentCalculator habits(int goodPercent, int badPercent) {
    return person -> person.habits().stream().mapToInt(h -> h.isGood() ? goodPercent : badPercent).sum();
}

诚然,getPremiumPercentByAge并不是那么容易扩展,这部分当然可以改进,但我认为这不是面试中最重要的部分。

请注意,虽然我使用lambdas来实现简洁的表达式,但是这个概念并不需要它,尽管这个解决方案在类被完全写出的情况下会更加冗长,但这不会减少它的好处。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/175816

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档