0
1

ミニ生命保険システムを作成 S05

Last updated at Posted at 2023-09-17

関連記事

はじめに

今回は、保険料の計算を実装する。保険料入力枠にフォーカスが当たると、自動的に保険料が計算されます。

003.gif

アイデア

保険商品によって保障内容が異なり、保険料の計算も異なる。それでも、商品サービスの高い凝集性と単一責任の考え方に従って、Strategyパターンを使って保険料の計算を実装する。

  • P001 安心医療 => 料率表を使って保険料を計算する。
  • P002 安心年金 => 固定レートを使用して保険料を計算する。

新商品の保険料計算が既存のStrategyに一致する場合、そのStrategyを再利用することで開発をスピードアップできます。

実装

Premium.png

料率表を使って保険料を計算する

PremiumCalculateWithTable
@Component
public class PremiumCalculateWithTable implements PremiumCalculate {
    @Override
    public BigDecimal calculate(PremiumCalculateRequest request) {
        Rate rate = rateRepository.findByProductIdAndAgeAndGender(
                request.getProductId(), request.getAge(), request.getGender());
        return request.getAmount().multiply(rate.getRate()).setScale(0, RoundingMode.CEILING);
    }
}
  • 検索料率
    DB.jpg

固定レートを使用して保険料を計算する

PremiumCalculateWithFixedRate
@Component
public class PremiumCalculateWithFixedRate implements PremiumCalculate {
    @Override
    public BigDecimal calculate(PremiumCalculateRequest request) {
        return request.getAmount()
                      .divide(new BigDecimal(request.getTerm()), RoundingMode.HALF_DOWN)
                      .multiply(new BigDecimal(1.10))
                      .setScale(0, RoundingMode.CEILING);
    }
}

Strategyのロード

起動時に PremiumCalculateStrategyFactory に strategy をロードします。

PremiumCalculateStrategyFactory
package com.insurance.life.product.service.strategy.premium;

@Component
public class PremiumCalculateStrategyFactory {
    private Map<String, PremiumCalculate> strategyMap;

    public PremiumCalculateStrategyFactory(List<PremiumCalculate> strategies) {
        strategyMap = strategies.stream()
                .collect(Collectors.toMap(PremiumCalculate::getName, x -> x));
    }
    // Strategy をその名前で呼び出します。
    public PremiumCalculate getStrategy(String name) {
        return strategyMap.get(name);
    }
}

Config

Config で商品に使用する特定strategyを設定する。

Config
package com.insurance.life.product.entity;

@Entity
public class Config implements Serializable {
    ...

    private int minAge;
    private int maxAge;
    // Strategy名前 
    private String premiumCalculateStrategyName;

    ...
}

Strategyの呼び出し

CallPremiumCalculate.png

商品の初期化

 Config config = new Config(18, 60,
            new BigDecimal(300000),
            "PremiumCalculateWithTable", // Strategy名前
            Arrays.asList(Term.YEAR_1, Term.YEAR_3, Term.YEAR_10, Term.YEAR_20),
            Arrays.asList(PaymentType.TYPE_MONTH));

Product product = new Product("P001", "安心医療", config);
repository.save(product);

料率表の初期化

private void initRate() {
    rateRepository.deleteAll();
    Rate rate;

    for (int i = 10; i < 80; i++) {
        rate = new Rate("P001", i, "F",
                new BigDecimal(1   + i/1000.0).divide(
                        new BigDecimal(100), RoundingMode.HALF_DOWN).setScale(6, RoundingMode.HALF_DOWN));

        rateRepository.save(rate);

        rate = new Rate("P001", i, "M",
                new BigDecimal(1.1 + i/1000.0).divide(
                        new BigDecimal(100), RoundingMode.HALF_DOWN).setScale(6, RoundingMode.HALF_DOWN));
        rateRepository.save(rate);
    }
}

Source Code

終わり

機能が増えれば、Bad Smellも増える。

  • MainViewと依存サービスはどのようにデカップリングするのですか?
  • 重複するDTO、最適化するには?
  • RestApi宣言はどのように最適化できるか?

最後まで読んでいただきありがとうございました。何かご提案やご質問がありましたら、コメントをお待ちしています。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1