Sponsored Link •
|
Advertisement
|
Account
ObjectAccount
still means to offer three services:
okToWithdraw()
, withdraw()
, and deposit()
1 package com.artima.examples.account.ex2; 2 3 /** 4 * Represents a bank account with overdraft protection. Instances 5 * of this class are instantiated with a specified maximum 6 * overdraft. If a client attempts to withdraw more than the 7 * current account balance, the bank may loan the amount in 8 * excess of the balance to the client. The overdraft maximum 9 * passed to an <code>OverdraftAccount</code>'s constructor 10 * is the maximum amount the bank will lend to the client in 11 * this manner. When a client makes a deposit, the bank will 12 * pay itself back first before increasing the account's balance. 13 * 14 * <p> 15 * Money is stored in this account in integral units. Clients 16 * can use this account to store any kind of value, such as money 17 * or points, etc. The meaning of the integral units stored in 18 * this account is a decision of the client that instantiates the 19 * account. The maximum amount of units that can be stored as 20 * the current balance of an <code>Account</code> is Long.MAX_VALUE. 21 */ 22 public class OverdraftAccount { 23 24 /** 25 * Helper back-end object 26 */ 27 private Account account = new Account(); 28 29 /** 30 * The maximum amount the bank will loan to the client. 31 */ 32 private final long overdraftMax; 33 34 /** 35 * The current amount the bank has loaned to the client 36 * which has not yet been repaid. This must be zero to 37 * overdraftMax. 38 */ 39 private long overdraft; 40 41 /** 42 * Constructs a new <code>OverdraftAccount</code> with the 43 * passed <code>overdraftMax</code>. 44 * 45 * @param overdraftMax the maximum amount the bank will loan 46 * to the client 47 */ 48 public OverdraftAccount(long overdraftMax) { 49 this.overdraftMax = overdraftMax; 50 } 51 52 /** 53 * Returns the current overdraft, the amount the bank has 54 * loaned to the client that has not yet been repaid. 55 * 56 * @returns the current overdraft 57 */ 58 public long getOverdraft() { 59 return overdraft; 60 } 61 62 /** 63 * Returns the overdraft maximum, the maximum amount the 64 * bank will allow the client to owe it. For each instance 65 * of <code>OverdraftAccount</code>, the overdraft maximum 66 * is constant. 67 * 68 * @returns the overdraft maximum 69 */ 70 public long getOverdraftMax() { 71 return overdraftMax; 72 } 73 74 /** 75 * Gets the current balance of this <code>OverdraftAccount</code> 76 * 77 * @returns the current balance 78 */ 79 public long getBalance() { 80 return account.getBalance(); 81 } 82 83 /** 84 * Withdraws exactly the passed amount from the 85 * <code>Account</code>. If the passed amount is 86 * less than or equal to the current balance, all withdrawn 87 * funds will be taken from the balance, and the balance 88 * will be decremented by the passed amount. If the passed amount 89 * exceeds the current balance, the bank may loan the client the 90 * difference. The bank will make the loan only if the difference 91 * between the passed amount and the balance is less than or equal to 92 * the available overdraft. The available overdraft is equal to 93 * the current overdraft (the amount already loaned to the client and 94 * not yet repaid), subtracted from the overdraft maximum, which 95 * is passed to the constructor of any <code>OverdraftAccount</code>. 96 * 97 * <p> 98 * If the passed amount less the current balance is less than or equal 99 * to the available overdraft, the <code>withdraw</code> method returns 100 * the requested amount, sets the current balance to zero, and records 101 * the loan. Otherwise, if the passed amount less the current balance 102 * exceeds the available overdraft, the <code>withdraw</code> method throws 103 * <code>InsufficientFundsException</code>. 104 * 105 * @param amount amount to withdraw 106 * @returns amount withdrawn from the <code>Account</code> 107 * @throws InsufficientFundsException if the <code>Account</code> 108 * contains insufficient funds for the requested withdrawal 109 */ 110 public long withdraw(long amount) 111 throws InsufficientFundsException { 112 113 long balance = account.getBalance(); 114 if (balance >= amount) { 115 116 // Balance has sufficient funds, just take the 117 // money from the balance. 118 balance -= amount; 119 return amount; 120 } 121 122 long shortfall = amount - balance; 123 long extraAvailable = overdraftMax - overdraft; 124 125 if (shortfall > extraAvailable) { 126 throw new InsufficientFundsException(shortfall - extraAvailable); 127 } 128 overdraft += shortfall; 129 account.withdraw(amount - shortfall); 130 131 return amount; 132 } 133 134 /** 135 * Deposits exactly the passed amount into the <code>Account</code>. 136 * If the current overdraft is zero, the balance will be increased 137 * by the passed amount. Otherwise, the bank will attempt to pay 138 * off the overdraft first, before increasing the current balance 139 * by the amount remaining after the overdraft is repaid, if any. 140 * 141 * <p> 142 * For example, if the balance is 200, the overdraft is 100, and the 143 * <code>deposit</code> method is invoked with a passed <code>amount</code> 144 * of 50, the bank would use all 50 of those monetary units to pay down 145 * the overdraft. The overdraft would be reduced to 50 and the balance would 146 * remain at 200. If subsequently, the client deposits another 100 units, 147 * the bank would use 50 of those units to pay off the overdraft loan and 148 * direct the remaining 50 into the balance. The new overdraft would 149 * be 0 and the new balance would be 250. 150 * 151 * @param amount amount to deposit 152 * @throws ArithmeticException if requested deposit would cause the 153 * balance of this <code>Account</code> to exceed Long.MAX_VALUE. 154 */ 155 public void deposit(long amount) { 156 if (overdraft > 0) { 157 if (amount < overdraft) { 158 overdraft -= amount; 159 } 160 else { 161 long diff = amount - overdraft; 162 overdraft = 0; 163 account.deposit(diff); 164 } 165 } 166 else { 167 account.deposit(amount); 168 } 169 } 170 }
Account
object on the heap:
Another relationship similar to composition is aggregation. Like composition, the aggregation relationship entails a front-end object holding references in instance variables to back-end objects. The difference is intent. In a composition relationship, the front-end objects enlist the help of the back-end objects to fulfill the front-end's semantic contract. In an aggregation relationship, front-end objects merely serve as containers for back-end objects. Front-end objects in an aggregation relationship don't invoke methods on back-ends, they just hold them.
In a non-garbage collected language, such as C++, it is more important to differentiate between composition and aggregation. Roughly speaking, if a back-end object is in a composition relationship in C++, the back-end should in general be deleted by the destructor of the front-end. By contrast, if a back-end object is held in an aggregation relationship in C++, the back-end object should in general survive the destruction of the front-end. Given that Java objects are never explicitly destroyed, just released to the whims of the garbage collector, the composition/aggregation distinction is not as important in Java.
On the other hand, it is important in Java to differentiate between composition and aggregation when
implementing the clone
method. Mutable back-end objects held in a composition relationship
should be cloned along with the front-end object. In an aggregation relationship, by contrast, back-end
objects should not be cloned. Put another way, composition implies deep copy; aggregation implies
shallow copy. This distinction is discussed in guideline ??? and the Clonable Object Recipe in
Appendix A.
composition sometimes models the HAS-A relationship, but not always. Here mention why I avoided HAS-A, that design patterns give a much richer discussion of composition relationships -- see chapter 4.
Discuss aggregation in that you are holding onto objects for the client, but not delegating to those objects yourself. Mention the collections stuff, messengers for multi-valued returns, arrays, tuples.
Sponsored Links
|