在一次面试中,我尝试了一次编码练习,在这里定义和实现了(问题自述):
https://gitlab.com/vineet_康复中心/健康保险-保费-报价-发电机-2
它最初是一个简单的、单一的java类程序。
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()方法中调用它们。
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)。
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原则。他建议我应该使它更面向对象。此外,仅仅因为有一个类&接口,并不意味着它是一种策略模式。
我不太理解这些评论。有人能回顾一下这个&让我知道一个很好的编码方法吗?或者为什么我的实现如此糟糕?有什么好方法使它更面向对象,以及策略模式的正确用法是什么?
发布于 2017-09-17 20:01:48
一个良好的OOP设计是开放的扩展和封闭的修改。单方法实现与此相去甚远。
我认为这个练习的目的是能够从部件中构建一个高级计算器,这样您就可以轻松地修改可能发生变化的部分。这些零件是什么?
百分比修饰符部分本质上是接受Person并返回百分比的函数。您可以提供这样的部件来简化计算机的构建,例如:
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();
}然后,使用构建器模式,您可以从如下部分构建一个计算器:
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是构造函数参数,因为它们对于计算器是绝对必要的,因此有必要预先要求它们,以便实现的其余部分无需进一步验证就可以存在。
您可能会注意到,badHabits和goodHabits迭代了两次习惯集合。这很可能可以忽略不计。但是如果不是,那么通过添加另一个部分就可以很容易地修复:
PremiumPercentCalculator habits(int goodPercent, int badPercent) {
return person -> person.habits().stream().mapToInt(h -> h.isGood() ? goodPercent : badPercent).sum();
}诚然,getPremiumPercentByAge并不是那么容易扩展,这部分当然可以改进,但我认为这不是面试中最重要的部分。
请注意,虽然我使用lambdas来实现简洁的表达式,但是这个概念并不需要它,尽管这个解决方案在类被完全写出的情况下会更加冗长,但这不会减少它的好处。
https://codereview.stackexchange.com/questions/175816
复制相似问题