OOP Project: Mortgage Calculator
Contents
OOP Project: Mortgage Calculator#
Note
Use OOP principals to refactoring the Mortgage Calculator.
Base on the principals of Encapsulation and Abstraction, we decided to construct 3 classes:
Console: implement
readNumber
MortgageReport: all about presentation
MortgageCalculator: all about calculation
The Console#
package com.codewithmosh;
import java.util.Scanner;
public class Console {
private static final Scanner scanner = new Scanner(System.in);
public static double readNumber(String prompt, double min, double max) {
double value;
while (true) {
System.out.print(prompt);
value = scanner.nextDouble();
if (value >= min && value <= max) {
break;
}
System.out.println("Enter a value between " + min + " and " + max);
}
return value;
}
}
Tip
IntelliJ Safe refactor: Refactor > Refactor this > Move to another class.
The MortgageCalculator#
Here, additionally, we calculate the balance remained after each month:
\[
P\frac{(1+r)^{n} - (1+r)^{k}}{(1+r)^{n} -1}
\]
where \(P\) is the principal, \(r\) is the monthly interest rate, \(n\) is the total months, \(k\) is the months we already payed.
package com.codewithmosh;
public class MortgageCalculator {
private final byte MONTHS_IN_YEAR = 12;
private final byte PERCENT = 100;
private int principal;
private float annualInterestRate;
private byte years;
// constructor
public MortgageCalculator(int principal, float annualInterestRate, byte years) {
this.principal = principal;
this.annualInterestRate = annualInterestRate;
this.years = years;
}
public double calculateMortgage() {
float monthlyInterestRate = getMonthlyInterestRate();
int numberOfPayments = getNumberOfPayments();
return principal * (monthlyInterestRate * Math.pow(1 + monthlyInterestRate, numberOfPayments) /
(Math.pow(1 + monthlyInterestRate, numberOfPayments) - 1));
}
// return one balance
private double calculateBalance(int paymentsMade) {
float monthlyInterestRate = getMonthlyInterestRate();
int numberOfPayments = getNumberOfPayments();
return principal *
(Math.pow(1 + monthlyInterestRate, numberOfPayments) - Math.pow(1 + monthlyInterestRate, paymentsMade))
/ (Math.pow(1 + monthlyInterestRate, numberOfPayments) - 1);
}
// return balances
public double[] getRemainingBalances() {
double[] balances = new double[getNumberOfPayments()];
for (short month = 0; month < balances.length; month++) {
balances[month] = calculateBalance(month);
}
return balances;
}
private float getMonthlyInterestRate() {
return annualInterestRate / PERCENT / MONTHS_IN_YEAR;
}
private int getNumberOfPayments() {
return years * MONTHS_IN_YEAR;
}
}
Tip
Use Generate -> Constructor in IntelliJ to easily create a constructor.
The MortgageReport#
Initialize a MortgageReport using a MortgageCalculator.
package com.codewithmosh;
import java.text.NumberFormat;
public class MortgageReport {
private MortgageCalculator calculator;
private final NumberFormat currency;
// constructor
public MortgageReport(MortgageCalculator calculator) {
this.calculator = calculator;
currency = NumberFormat.getCurrencyInstance();
}
public void printMortgage() {
double mortgage = calculator.calculateMortgage();
System.out.println();
System.out.println("MORTGAGE");
System.out.println("--------");
System.out.println("Mortgage: " + currency.format(mortgage));
}
public void printPaymentSchedule() {
System.out.println();
System.out.println("PAYMENT SCHEDULE");
System.out.println("----------------");
for (double balance :
calculator.getRemainingBalances()) {
System.out.println(currency.format(balance));
}
}
}
The Main Class#
package com.codewithmosh;
public class Main {
public static void main(String[] args) {
// return double and explicit casting
int principal = (int)Console.readNumber("Principal: ", 1000, 1_000_000);
float annualInterestRate = (float)Console.readNumber("annualInterestRate: ", 1, 30);
byte years = (byte)Console.readNumber("Years: ", 1, 30);
MortgageCalculator calculator = new MortgageCalculator(principal, annualInterestRate, years);
MortgageReport report = new MortgageReport(calculator);
report.printMortgage();
report.printPaymentSchedule();
}
}
Beatiful!