Java bank - Inheritance

Let us assume that one day our Java bank will need an account to withdraw even if the withdrawal amount is greater than the balance. This account can have a negative balance. If inheritance is applied, the existing account class can be superclass without change. And you can make an account with a negative balance as a subclass. From now on, let's call an account that has a negative balance as a minus account. A Minus account class only need to override the withdraw() of the superclass account class. The addAccount(String accountNo, String name, long balance) method of the bank class must determine whether the account to be created is a regular account or a negative account. To do so, add the following parameters: addAccount(String accountNo, String name, long balance, String kind) {..}. The kind parameter is assigned either the normal or minus character.

Account.java
package net.java_school.bank;

import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class Account {
	private String accountNo;
	private String name;
	protected long balance;
	private String kind;
	protected List<Transaction> transactions = new ArrayList<Transaction>();
	
	static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd");
	static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");
	static final String DEPOSIT = "Deposit";
	static final String WITHDRAW = "Withdrawal";
	static final String NORMAL = "Normal";
	static final String MINUS = "Minus";
	static final NumberFormat NUMBER_FORMAT = NumberFormat.getInstance();

	public Account() {}
	
	public Account(String accountNo, String name, String kind) {
		this.accountNo = accountNo;
		this.name = name;
		this.kind = kind;
	}
	
	public Account(String accountNo, String name, long balance, String kind) {
		this.accountNo = accountNo;
		this.name = name;
		this.balance = balance;
		this.kind = kind;
	}
	
	public void deposit(long amount) {
		balance = balance + amount;
		Transaction transaction = new Transaction();
		Calendar cal = Calendar.getInstance();
		Date date = cal.getTime();
		transaction.setTransactionDate(Account.DATE_FORMAT.format(date));
		transaction.setTransactionTime(Account.TIME_FORMAT.format(date));
		transaction.setAmount(amount);
		transaction.setKind(Account.DEPOSIT);
		transaction.setBalance(this.balance);
		transactions.add(transaction);
	}
	
	public void withdraw(long amount) {
		if (amount > this.balance) {
			return;
		}
		balance = balance - amount;
		Transaction transaction = new Transaction();
		Calendar cal = Calendar.getInstance();
		Date date = cal.getTime();
		transaction.setTransactionDate(Account.DATE_FORMAT.format(date));
		transaction.setTransactionTime(Account.TIME_FORMAT.format(date));
		transaction.setAmount(amount);
		transaction.setKind(Account.WITHDRAW);
		transaction.setBalance(this.balance);
		transactions.add(transaction);
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getAccountNo() {
		return accountNo;
	}
	
	public void setAccountNo(String accountNo) {
		this.accountNo = accountNo;
	}
	
	public long getBalance() {
		return balance;
	}
	
	public void setBalance(long balance) {
		this.balance = balance;
	}
	
	public List<Transaction> getTransactions() {
		return transactions;
	}
	
	public void setTransactions(List<Transaction> transactions) {
		this.transactions = transactions;
	}
	
	public String getKind() {
		return kind;
	}
	
	public void setKind(String kind) {
		this.kind = kind;
	}
	
	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append(accountNo);
		sb.append("|");		
		sb.append(name);
		sb.append("|");
		sb.append(Account.NUMBER_FORMAT.format(balance));
		sb.append("|");
		sb.append(kind);
			
		return sb.toString();
	}

}

Modify the toString() method of the Transaction class as follows:

Transaction.java
@Override
public String toString() {
	StringBuilder sb = new StringBuilder();
	sb.append(this.transactionDate);
	sb.append("|");
	sb.append(this.transactionTime);
	sb.append("|");
	sb.append(this.kind);
	sb.append("|");
	sb.append(Account.NUMBER_FORMAT.format(this.amount));
	sb.append("|");
	sb.append(Account.NUMBER_FORMAT.format(this.balance));
	
	return sb.toString();
}
MinusAccount.java
package net.java_school.bank;

import java.util.Calendar;
import java.util.Date;

public class MinusAccount extends Account {
	
	public MinusAccount() {}
	
	public MinusAccount(String accountNo, String name, String kind) {
		super(accountNo, name, kind);
	}

	public MinusAccount(String accountNo, String name, long balance, String kind) {
		super(accountNo, name, balance, kind);
	}
	
	@Override
	public void withdraw(long amount) {
		balance = balance - amount;
		Transaction transaction = new Transaction();
		Calendar cal = Calendar.getInstance();
		Date date = cal.getTime();
		transaction.setTransactionDate(Account.DATE_FORMAT.format(date));
		transaction.setTransactionTime(Account.TIME_FORMAT.format(date));
		transaction.setAmount(amount);
		transaction.setKind(Account.WITHDRAW);
		transaction.setBalance(this.balance);
		transactions.add(transaction);
	}
	
}
Bank.java
package net.java_school.bank;

import java.util.ArrayList;
import java.util.List;

public class Bank {
	private List<Account> accounts = new ArrayList<Account>();

	public void addAccount(String accountNo, String name, String kind) {
		Account account = getAccount(accountNo);
		if (account == null) {
			if (Account.NORMAL.equals(kind)) {
				accounts.add(new Account(accountNo, name, kind));
			} else if (Account.MINUS.equals(kind)) {
				accounts.add(new MinusAccount(accountNo, name, kind));
			}
		}
	}
	
	public void addAccount(String accountNo, String name, long balance, String kind) {
		Account account = getAccount(accountNo);
		if (account == null) {
			if (Account.NORMAL.equals(kind)) {
				accounts.add(new Account(accountNo, name, balance, kind));
			} else if (Account.MINUS.equals(kind)) {
				accounts.add(new MinusAccount(accountNo, name, balance, kind));
			}
		}
	}
	
	public Account getAccount(String accountNo) {
		int totalAccount = accounts.size();
		
		for (int i = 0; i < totalAccount; i++) {
			if (accountNo.equals(accounts.get(i).getAccountNo())) {
				return accounts.get(i);
			}
		}
		
		return null;
	}
	
	public List<Account> findAccountByName(String name) {
		List<Account> matched = new ArrayList<Account>();
		int totalAccount = accounts.size();
		
		for (int i = 0; i < totalAccount; i++) {
			if (name.equals(accounts.get(i).getName())) {
				matched.add(accounts.get(i));
			}
		}
		
		return matched;
	}
	
	public List<Account> getAccounts() {
		return accounts;
	}
  
}
Test.java
package net.java_school.bank;

import java.util.List;

public class Test {
    static final String ACCOUNTS_HEADING = "Account No|Owner|Balance|N/M";
    static final String TRANSACTIONS_HEADING = "Date|Time|D/W|Amount|Balance";

    public static void main(String[] args) {
    
        //Create test accounts
        Bank bank = new Bank();
        bank.addAccount("101", "Alison", Account.NORMAL); 
        bank.addAccount("202", "Bill", Account.NORMAL);
        bank.addAccount("303", "Carol", Account.NORMAL);
        bank.addAccount("404", "Alison", Account.MINUS);

        //1. Print out the total account list.
        System.out.println("1. Print out the total account list");
        List<Account> accounts = bank.getAccounts();
        int totalAccount = accounts.size();
        System.out.println(Test.ACCOUNTS_HEADING);
        for (int i = 0; i < totalAccount; i++) {
	        System.out.println(accounts.get(i));
        }
       
        System.out.println();
        
        //2. Deposit $ 10 into 101 account.
        System.out.println("2. Deposit $ 10 into 101 account.");		
        Account hong = bank.getAccount("101");
        hong.deposit(10);
        System.out.println(Test.ACCOUNTS_HEADING);
        System.out.println(hong);

        System.out.println();
		
        //3. Withdraw $ 5 from 101 account.
        System.out.println("3. Withdraw $ 5 from 101 account.");		
        hong.withdraw(5);
        System.out.println(Test.ACCOUNTS_HEADING);
        System.out.println(hong);

        System.out.println();
        
        //4. Print transaction history of the 101 account.
        System.out.println("4. Print transaction history of the 101 account.");		
        List<Transaction> transactions = hong.getTransactions();
        int totalTransaction = transactions.size();
        System.out.println(Test.TRANSACTIONS_HEADING);
        for (int i = 0; i < totalTransaction; i++) {
	        System.out.println(transactions.get(i));
        }
        
        System.out.println();

        //5. Find your account by customer name.
        System.out.println("5. Find Alison's Account.");
        List<Account> matched = bank.findAccountByName("Alison");
        System.out.println(Test.ACCOUNTS_HEADING);

        for (Account account : matched) {
	        System.out.println(account);
        }
        
        System.out.println();
                        
        //6. Withdraw $ 5 from 404 account.
        System.out.println("6. Withdraw $ 5 from 404 account.");		
        Account minus = bank.getAccount("404");
        minus.withdraw(5);
        System.out.println(Test.ACCOUNTS_HEADING);
        System.out.println(minus);
        
    }

}

TODO

Create following custom exceptions and apply them to the example.

  • DuplicateAccountException
  • InsufficientBalanceException