首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 面向對象建模實戰:房貸業務領域驅動設計演示

     編輯:Java 相關知識

面向對象不僅是語法糖,更是將業務複雜度轉化為可維護代碼結構的思維工具。本文以房貸業務為例,演示從需求分析到領域模型構建、服務層設計的完整 OO 建模過程,展示封裝、繼承、多態在實戰中的應用。

一、業務需求梳理

  1. 客戶可擁有多套房貸
  2. 簽約後監控還款計劃執行
  3. 自動還款:單筆款項匹配多筆貸款
  4. 支持提前還款、期限調整、利率變更
  5. 滯納金計算與壞賬識別

二、領域對象識別與屬性定義

領域對象核心屬性業務含義
Customerusername, money借款人,持有可用資金
Housenum, price, rate, years抵押物,含價格、利率、年限
Creditcustomer, houses[], backTime, toPay(Map<House,Double>)貸款合約,關聯客戶、房產、每月應還金額映射
Agreementcredit, isContinue, amercement法律合同,狀態機:正常/壞賬/終止

三、核心代碼實現

1. 領域實體類

public class Customer {
    private String username;
    private double money;
    // getter/setter 省略
}

public class House {
    private String num;      // 房號 如 "3#116"
    private double price;    // 總價
    private double rate;     // 月利率
    private int years;       // 貸款年限
    // getter/setter 省略
}

public class Credit {
    private Customer customer;
    private List<House> houses;
    private int backTime;                 // 還款日
    private Map<House, Double> toPay;     // 每套房每月應還額
    // getter/setter 省略
}

public class Agreement {
    private Credit credit;
    private boolean isContinue = true;    // 合同狀態
    private double amercement;            // 累計滯納金
    // getter/setter 省略
}

2. 服務介面與實現(策略模式預留擴展)

public interface BankService {
    Credit buyHouses(Customer customer, List<House> houses);
    Agreement signAgreement(Customer customer, Credit credit);
    double repay(int period, Agreement agreement, double amount, Customer customer);
    Map<House, Double> adjustRate(House house, double newRate);
    Map<House, Double> adjustTerm(House house, int newYears);
}

public class BankServiceImpl implements BankService {
    @Override
    public Credit buyHouses(Customer customer, List<House> houses) {
        Credit credit = new Credit();
        credit.setCustomer(customer);
        credit.setHouses(houses);
        credit.setBackTime(1); // 默認每月 1 號
        
        // 計算每套房月供(等額本息簡化公式)
        Map<House, Double> toPay = new HashMap<>();
        for (House h : houses) {
            double monthlyRate = h.getRate();
            int months = h.getYears() * 12;
            double principal = h.getPrice();
            // 等額本息:P * r * (1+r)^n / ((1+r)^n - 1)
            double monthly = principal * monthlyRate * Math.pow(1+monthlyRate, months) 
                           / (Math.pow(1+monthlyRate, months) - 1);
            toPay.put(h, monthly);
        }
        credit.setToPay(toPay);
        return credit;
    }

    @Override
    public Agreement signAgreement(Customer customer, Credit credit) {
        Agreement ag = new Agreement();
        ag.setCredit(credit);
        return ag;
    }

    @Override
    public double repay(int period, Agreement agreement, double amount, Customer customer) {
        // 簡化:按 toPay 比例分配還款,計算滯納金
        double totalDue = agreement.getCredit().getToPay().values().stream().mapToDouble(d -> d).sum();
        if (amount < totalDue) {
            agreement.setAmercement(agreement.getAmercement() + (totalDue - amount) * 0.01); // 1% 滯納金
        }
        customer.setMoney(customer.getMoney() - amount);
        return agreement.getAmercement();
    }

    @Override
    public Map<House, Double> adjustRate(House house, double newRate) {
        house.setRate(newRate);
        return recalculate(house); // 重算月供
    }

    @Override
    public Map<House, Double> adjustTerm(House house, int newYears) {
        house.setYears(newYears);
        return recalculate(house);
    }
    
    private Map<House, Double> recalculate(House h) {
        Map<House, Double> m = new HashMap<>();
        // 同 buyHouses 計算邏輯
        return m;
    }
}

3. 主流程編排

public class BankApp {
    public static void main(String[] args) {
        Customer customer = new Customer();
        customer.setUsername("董林美美");
        customer.setMoney(1000000);

        List<House> houses = Arrays.asList(
            new House("3#116", 1500000, 0.004, 20),
            new House("4#112", 1100000, 0.0035, 30),
            new House("1#001", 2000000, 0.003, 10)
        );

        BankService bs = new BankServiceImpl();
        Credit credit = bs.buyHouses(customer, houses);
        Agreement agreement = bs.signAgreement(customer, credit);

        if (!agreement.isContinue()) return;

        // 模擬第 1 期還款
        double amercement = bs.repay(1, agreement, 111111, customer);
        
        // 檢查壞賬:滯納金超過應還額 1/3 視為壞賬
        for (Map.Entry<House, Double> e : credit.getToPay().entrySet()) {
            if (amercement >= e.getValue() / 3) {
                agreement.setContinue(false);
                System.out.println(customer.getUsername() + " 賬戶壞賬,合同終止");
                break;
            }
        }

        // 利率/期限調整演示
        bs.adjustRate(houses.get(2), 0.005);
        bs.adjustTerm(houses.get(2), 15);
        
        // 輸出每月還款明細
        for (Map.Entry<House, Double> e : credit.getToPay().entrySet()) {
            System.out.printf("%s 房子 %s 每月還款: %.2f%n", 
                customer.getUsername(), e.getKey().getNum(), e.getValue());
        }
    }
}

四、設計亮點與擴展點

  1. 豐富領域模型:業務邏輯封裝在 Credit、Agreement 中,而非貧血模型只存數據。
  2. 策略模式預留:adjustRate/adjustTerm 可替換為 RateStrategy 介面,支持等額本息/等額本金/先息後本多種算法熱插拔。
  3. 觀察者模式解耦:利率/期限變更時,發布 LoanTermsChangedEvent,通知風控、通知、報表等下游系統,避免服務層膨脹。
  4. 狀態機管理 Agreement:isContinue 可擴展為枚舉 NORMAL, OVERDUE, BAD_DEBT, SETTLED,配合狀態模式處理狀態轉換邏輯。
  5. 值對象:Money、InterestRate、Period 封裝驗證邏輯,消除基本類型痴迷。

五、DDD 分層架構映射

層職責本例對應
表現層HTTP/控制台交互BankApp.main
應用層用例編排、事務邊界BankService 介面
領域層核心業務規則、不變式Customer, House, Credit, Agreement
基礎設施層持久化、外部服務(未實現)JPA Repository

這個例子雖然簡化,但展示了 OO 建模的核心價值:用領域語言命名類與方法,將業務規則封裝在領域對象中,服務層只編排不包含業務判斷。隨著業務演進,可平滑引入聚合根、領域事件、CQRS 等進階模式,保持架構清晰可擴展。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved