class ATOverdrawableSavingsAccount extends ATSavingsAccount { public ATOverdrawableSavingsAccount(long max) { super(max); } // This account permits an overdrawn state! public synchronized void deposit(long amount) { balance += amount; checking.tryTransfer(); } } public class AccountTest { private static final int TRESHOLD = 1000; private static final int MAX_TRANSFER = 100; public static void main(String[] args) throws InsufficientFunds { ATOverdrawableSavingsAccount savings = new ATOverdrawableSavingsAccount(MAX_TRANSFER); ATCheckingAccount checking = new ATCheckingAccount(TRESHOLD); savings.initChecking(checking); checking.initSavings(savings); // First, we will force the savings account into an overdrawn state and // "enjoy" the consequences of further money transactions, though. // Oooopss, since the joint action will be triggered always and not // only when a savings account's balance increases, we loose money // immediately. savings.withdraw(10); System.out.println("Savings balance = " + savings.balance()); System.out.println("(expected checking balance = 0)..."); System.out.println("Checking balance = " + checking.balance()); // Oooopss, since the joint action will be triggered always and not // only when a checking account's balance decreases, we loose money // immediately (since, the checking account's balance will be below a // treshold, thankfully for the first transaction and money loss). checking.deposit(TRESHOLD + 1); System.out.println("\n(expected checking balance = 1001) ..."); System.out.println("Checking balance = " + checking.balance()); checking.withdraw(2); // Checking's balance is below treshold now! // We've lost our money again... System.out.println("\n(expected checking balance = 999) ..."); System.out.println("Checking balance = " + checking.balance()); } }