interface
.
interface
s to define large families or to say "What objects can do."
interface
extension to decouple services or restrict the semantic contract.
interface
.
OverdraftAccount
reuses all methods in Account
and OverdraftEventManager
OverdraftAccount
to a method that expects an Account
or OverdraftEventManager
1 package com.artima.examples.account.ex3; 2 3 /** 4 * Represents a bank account with overdraft protection. Instances of this 5 * class are instantiated with a specified maximum overdraft. If a client 6 * attempts to withdraw more than the current account balance, the bank may 7 * loan the amount in excess of the balance to the client. The overdraft 8 * maximum passed to an <code>OverdraftAccount</code>'s constructor is the 9 * maximum amount the bank will lend to the client in this manner. When a 10 * client makes a deposit, the bank will pay itself back first before 11 * increasing the account's balance. 12 * 13 * <p> 14 * Money is stored in this account in integral units. Clients can use this 15 * account to store any kind of value, such as money or points, etc. The 16 * meaning of the integral units stored in this account is a decision of the 17 * client that instantiates the account. The maximum amount of units that can 18 * be stored as the current balance of an <code>Account</code> is 19 * Long.MAX_VALUE. 20 */ 21 public class OverdraftAccount { 22 23 /** 24 * Helper back-end <code>Account</code> object 25 */ 26 private Account account = new Account(); 27 28 /** 29 * Helper back-end <code>OverdraftEventManager</code> object 30 */ 31 private OverdraftEventManager eventMan 32 = new OverdraftEventManager(); 33 34 /** 35 * The maximum amount the bank will loan to the client. 36 */ 37 private final long overdraftMax; 38 39 /** 40 * The current amount the bank has loaned to the client which has not yet 41 * been repaid. This value must at all times be greater than or equal to 42 * zero, and less than or equal to <code>overdraftMax</code>. If this 43 * value is greater than zero, then the balance of the helper 44 * <code>Account</code> (referenced from the <code>account</code> 45 * instance variable) must be exactly zero. 46 */ 47 private long overdraft; 48 49 /** 50 * Constructs a new <code>OverdraftAccount</code> with the passed 51 * overdraft maximum. 52 * 53 * @param overdraftMax the maximum amount the bank will loan to the 54 * client 55 */ 56 public OverdraftAccount(long overdraftMax) { 57 this.overdraftMax = overdraftMax; 58 } 59 60 /** 61 * Returns the current overdraft, the amount the bank has loaned to the 62 * client that has not yet been repaid. 63 * 64 * @return the current overdraft 65 */ 66 public long getOverdraft() { 67 return overdraft; 68 } 69 70 /** 71 * Returns the overdraft maximum, the maximum amount the bank will allow 72 * the client to owe it. For each instance of 73 * <code>OverdraftAccount</code>, the overdraft maximum is constant. 74 * 75 * @return the overdraft maximum 76 */ 77 public long getOverdraftMax() { 78 return overdraftMax; 79 } 80 81 /** 82 * Gets the current balance of this <code>OverdraftAccount</code>. 83 * 84 * @return the current balance 85 */ 86 public long getBalance() { 87 return account.getBalance(); 88 } 89 90 /** 91 * Withdraws the passed amount from this <code>OverdraftAccount</code>. 92 * If the passed amount is less than or equal to the current balance, all 93 * withdrawn funds will be taken from the balance, and the balance will 94 * be decremented by the passed amount. If the passed amount exceeds the 95 * current balance, the bank may loan the client the difference. The bank 96 * will make the loan only if the difference between the passed amount 97 * and the balance (the shortfall) is less than or equal to the available 98 * overdraft. The available overdraft is equal to the current overdraft 99 * (the amount already loaned to the client and not yet repaid), 100 * subtracted from the overdraft maximum, which is passed to the 101 * constructor of any <code>OverdraftAccount</code>. 102 * 103 * <p> 104 * If the passed amount is less than or equal to the current balance, the 105 * <code>withdraw</code> method decrements the current balance by the 106 * passed amount and returns the passed amount. If the passed amount is 107 * greater than the current balance, but the passed amount minus the 108 * current balance is less than or equal to the available overdraft, the 109 * <code>withdraw</code> method sets the current balance to zero, records 110 * the loan, and returns the requested amount. Otherwise, the passed 111 * amount minus the current balance exceeds the available overdraft, so 112 * the <code>withdraw</code> method throws 113 * <code>InsufficientFundsException</code>. 114 * 115 * Subclasses must withdraw at least the passed amount, but may 116 * effectively withdraw more. For example, if a subclass includes a 117 * notion of a withrawal fee, the subclass's implementation of this 118 * method may charge that fee by decrementing it from the account at the 119 * time of withdrawal. 120 * 121 * @param amount amount to withdraw 122 * @return amount withdrawn from the <code>OverdraftAccount</code> 123 * @throws InsufficientFundsException if the 124 * <code>OverdraftAccount</code> contains insufficient funds for the 125 * requested withdrawal 126 * @throws IllegalArgumentException if requested withdrawal amount is 127 * less than or equal to zero. 128 */ 129 public long withdraw(long amount) throws InsufficientFundsException { 130 131 if (amount <= 0) { 132 throw new IllegalArgumentException(); 133 } 134 135 long bal = account.getBalance(); 136 if (bal >= amount) { 137 138 // Balance has sufficient funds, so just take the 139 // money from the balance. 140 return account.withdraw(amount); 141 } 142 143 long shortfall = amount - bal; 144 long extraAvailable = overdraftMax - overdraft; 145 146 if (shortfall > extraAvailable) { 147 throw new InsufficientFundsException(shortfall 148 - extraAvailable); 149 } 150 overdraft += shortfall; 151 account.withdraw(amount - shortfall); 152 153 OverdraftEvent event = new OverdraftEvent(this, overdraft, 154 shortfall); 155 eventMan.fireOverdraftOccurred(event); 156 157 return amount; 158 } 159 160 /** 161 * Deposits the passed amount into the <code>OverdraftAccount</code>. If 162 * the current overdraft is zero, the balance will be increased by the 163 * passed amount. Otherwise, the bank will attempt to pay off the 164 * overdraft first, before increasing the current balance by the amount 165 * remaining after the overdraft is repaid, if any. 166 * 167 * <p> 168 * For example, if the balance is 0, the overdraft is 100, and the 169 * <code>deposit</code> method is invoked with a passed 170 * <code>amount</code> of 50, the bank would use all 50 of those monetary 171 * units to pay down the overdraft. The overdraft would be reduced to 50 172 * and the balance would remain at 0. If subsequently, the client 173 * deposits another 100 units, the bank would use 50 of those units to 174 * pay off the overdraft loan and direct the remaining 50 into the 175 * balance. The new overdraft would be 0 and the new balance would be 176 * 50. 177 * 178 * Subclasses may effectively deposit more or less than the passed amount 179 * into the <code>Account</code>. For example, if a subclass includes a 180 * notion of funds matching, the subclass implementation of this method 181 * may match some or all of the deposited amount at the time of deposit, 182 * effectively increasing the deposited amount. Or, if a subclass 183 * includes the notion of a deposit fee, the subclass's implementation of 184 * this method may charge that fee by decrementing it from the account at 185 * the time of deposit, effectively reducing the deposited amount. 186 * 187 * @param amount amount to deposit 188 * @throws ArithmeticException if requested deposit would cause the 189 * balance of this <code>Account</code> to exceed Long.MAX_VALUE. 190 * @throws IllegalArgumentException if requested withdrawal amount is 191 * less than or equal to zero. 192 */ 193 public void deposit(long amount) { 194 195 if (amount <= 0) { 196 throw new IllegalArgumentException(); 197 } 198 199 if (overdraft > 0) { 200 201 long amountRepaid = 0; 202 203 if (amount < overdraft) { 204 amountRepaid = amount; 205 overdraft -= amount; 206 } 207 else { 208 long diff = amount - overdraft; 209 amountRepaid = diff; 210 overdraft = 0; 211 account.deposit(diff); 212 } 213 214 OverdraftEvent event = new OverdraftEvent(this, overdraft, 215 amountRepaid); 216 eventMan.fireOverdraftRepaid(event); 217 } 218 else { 219 account.deposit(amount); 220 } 221 } 222 223 /** 224 * Adds the specified overdraft listener to receive overdraft events from 225 * this <code>OverdraftAccount</code>. If <code>l</code> is 226 * <code>null</code>, no exception is thrown and no action is performed. 227 * If <code>l</code> is already registered as a listener, no action is 228 * performed. 229 * 230 * @param l the <code>OverdraftEventListener</code> to add 231 */ 232 public void addOverdraftListener(OverdraftListener l) { 233 234 eventMan.addOverdraftListener(l); 235 } 236 237 /** 238 * Removes the specified overdraft listener so that it no longer receives 239 * overdraft events from this <code>OverdraftAccount</code>. This method 240 * performs no function, nor does it throw an exception, if the listener 241 * specified by the argument was not previously added to this component. 242 * If <code>l</code> is <code>null</code>, no exception is thrown and no 243 * action is performed. 244 * 245 * @param l the <code>OverdraftEventListener</code> to remove 246 */ 247 public void removeOverdraftListener(OverdraftListener l) { 248 249 eventMan.removeOverdraftListener(l); 250 } 251 } 1 package com.artima.examples.account.ex3; 2 3 /** 4 * Represents a bank account. Money is stored in this account in integral 5 * units. Clients can use this account to store any kind of value, such as 6 * money or points, etc. The meaning of the integral units stored in this 7 * account is a decision of the client that instantiates the account. The 8 * maximum amount of units that can be stored as the current balance of an 9 * <code>Account</code> is Long.MAX_VALUE. 10 */ 11 public class Account { 12 13 /** 14 * The current balance 15 */ 16 private long balance; 17 18 /** 19 * Withdraws exactly the passed amount from the <code>Account</code>. 20 * Subclasses must withdraw at least the passed amount, but may 21 * effectively withdraw more. For example, if a subclass includes a 22 * notion of a withrawal fee, the subclass's implementation of this 23 * method may charge that fee by decrementing it from the account at the 24 * time of withdrawal. 25 * 26 * @param amount amount to withdraw 27 * @return amount withdrawn from the <code>Account</code> 28 * @throws InsufficientFundsException if the <code>Account</code> 29 * contains insufficient funds for the requested withdrawal 30 * @throws IllegalArgumentException if the passed <code>amount</code> to 31 * withdraw is less than or equal to zero. 32 */ 33 public long withdraw(long amount) 34 throws InsufficientFundsException { 35 36 if (amount <= 0) { 37 throw new IllegalArgumentException(); 38 } 39 40 if (amount > balance) { 41 throw new InsufficientFundsException(amount - balance); 42 } 43 44 balance -= amount; 45 return amount; 46 } 47 48 /** 49 * Deposits exactly the passed amount into the <code>Account</code>. 50 * Subclasses may effectively deposit more or less than the passed amount 51 * into the <code>Account</code>. For example, if a subclass includes a 52 * notion of funds matching, the subclass implementation of this method 53 * may match some or all of the deposited amount at the time of deposit, 54 * effectively increasing the deposited amount. Or, if a subclass 55 * includes the notion of a deposit fee, the subclass's implementation of 56 * this method may charge that fee by decrementing it from the account at 57 * the time of deposit, effectively reducing the deposited amount. 58 * 59 * @param amount amount to deposit 60 * @throws ArithmeticException if requested deposit would cause the 61 * balance of this <code>Account</code> to exceed Long.MAX_VALUE. 62 * @throws IllegalArgumentException if requested deposit is less than 63 * or equal to zero. 64 */ 65 public void deposit(long amount) { 66 67 if (amount <= 0) { 68 throw new IllegalArgumentException(); 69 } 70 71 long newBal = balance + amount; 72 73 if (newBal < 0) { 74 throw new ArithmeticException(); 75 } 76 77 balance = newBal; 78 } 79 80 /** 81 * Gets the current balance of this <code>Account</code> 82 * 83 * @return the current balance 84 */ 85 public long getBalance() { 86 return balance; 87 } 88 } 89 1 package com.artima.examples.account.ex3; 2 3 import java.util.Set; 4 import java.util.Iterator; 5 import java.util.HashSet; 6 7 /** 8 * A class that manages registration and unregistration of 9 * <code>OverdraftListener</code>s and the firing of 10 * <code>OverdraftEvent</code>s. 11 * 12 * @author Bill Venners 13 */ 14 class OverdraftEventManager { 15 16 /** 17 * Unsynchronized <code>HashSet</code> to which listeners are added and 18 * removed via the synchronized methods <code>addOverdraftListener</code> 19 * and <code>removeOverdraftListener</code> methods. 20 */ 21 private HashSet listeners = new HashSet(); 22 23 /** 24 * Clone of the <code>listeners</code> <code>HashSet</code>, which is 25 * used by the <code>fireOverdraftOccurred</code> and 26 * <code>fireOverdraftRepaid</code> methods to propagate events. This 27 * <code>HashSet</code> always contains a most recent snapshot of the 28 * <code>listeners</code> <code>HashSet</code>, but this 29 * <code>HashSet</code> is never modified, only replaced. Because this 30 * <code>HashSet</code> is never modified, the fire methods can iterate 31 * through the set without synchronization. This implementation approach 32 * is geared towards providing optimum performance for the expected run 33 * time usage in which adding and removing listeners happens less 34 * frequently than firing events to those listeners. 35 */ 36 private Set listenersClone = new HashSet(); 37 38 /** 39 * Constructs a new <code>OverdraftEventManager</code>. The 40 * <code>OverdraftEventManager</code> starts its life with an empty 41 * listeners list. 42 */ 43 public OverdraftEventManager() { 44 } 45 46 /** 47 * Adds the specified overdraft listener to receive overdraft events. If 48 * <code>l</code> is <code>null</code>, no exception is thrown and no 49 * action is performed. If <code>l</code> is already registered as a 50 * listener, no action is performed. 51 * 52 * @param l the <code>OverdraftEventListener</code> to add 53 */ 54 public synchronized void addOverdraftListener(OverdraftListener l) { 55 56 listeners.add(l); 57 listenersClone = (Set) listeners.clone(); 58 } 59 60 /** 61 * Removes the specified overdraft listener so that it no longer receives 62 * overdraft events. This method performs no function, nor does it throw 63 * an exception, if the listener specified by the argument was not 64 * previously added to this component. If <code>l</code> is 65 * <code>null</code>, no exception is thrown and no action is performed. 66 * 67 * @param l the <code>OverdraftEventListener</code> to remove 68 */ 69 public synchronized void removeOverdraftListener(OverdraftListener l) { 70 71 listeners.remove(l); 72 listenersClone = (Set) listeners.clone(); 73 } 74 75 /** 76 * Fires overdraftOccurred events to registered listeners. 77 * 78 * @param event the <code>OverdraftEvent</code> to propagate 79 */ 80 public void fireOverdraftOccurred(OverdraftEvent event) { 81 82 Iterator it = listenersClone.iterator(); 83 while (it.hasNext()) { 84 OverdraftListener l = (OverdraftListener) it.next(); 85 l.overdraftOccurred(event); 86 } 87 } 88 89 /** 90 * Fires overdraftRepaid events to registered listeners. 91 * 92 * @param event the <code>OverdraftEvent</code> to propagate 93 */ 94 public void fireOverdraftRepaid(OverdraftEvent event) { 95 96 Iterator it = listenersClone.iterator(); 97 while (it.hasNext()) { 98 OverdraftListener l = (OverdraftListener) it.next(); 99 l.overdraftRepaid(event); 100 } 101 } 102 }
OverdraftAccount
inherits or invokes all methods in Account
and OverdraftEventManager
OverdraftAccount
to a method that expects a Account
or OverdraftEventManager
OverdraftAccount
to a method that expects a Account
or OverdraftEventManager
OverdraftAccount
can't reuse methods from Account
and OverdraftEventManager
, because none exist
Useful in 5% of design situations
Useful in 50% of design situations
interface
interface
s and composition)
interface
sOverdraftAccount
to a method that expects a Account
or OverdraftEventGenerator
OverdraftAccount
reuses all methods in BasicAccount
and OverdraftEventManager
1 package com.artima.examples.account.ex4; 2 3 /** 4 * Represents a bank account. Money is stored in this account in integral 5 * units. Clients can use this account to store any kind of value, such as 6 * money or points, etc. The meaning of the integral units stored in this 7 * account is a decision of the client that instantiates the account. The 8 * maximum amount of units that can be stored as the current balance of an 9 * <code>Account</code> is Long.MAX_VALUE. 10 */ 11 public interface Account { 12 13 /** 14 * Withdraws exactly the passed amount from the <code>Account</code>. 15 * Subclasses must withdraw at least the passed amount, but may 16 * effectively withdraw more. For example, if a subclass includes a 17 * notion of a withrawal fee, the subclass's implementation of this 18 * method may charge that fee by decrementing it from the account at the 19 * time of withdrawal. 20 * 21 * @param amount amount to withdraw 22 * @return amount withdrawn from the <code>Account</code> 23 * @throws InsufficientFundsException if the <code>Account</code> 24 * contains insufficient funds for the requested withdrawal 25 * @throws IllegalArgumentException if the passed <code>amount</code> to 26 * withdraw is less than or equal to zero. 27 */ 28 long withdraw(long amount) throws InsufficientFundsException; 29 30 /** 31 * Deposits exactly the passed amount into the <code>Account</code>. 32 * Subclasses may effectively deposit more or less than the passed amount 33 * into the <code>Account</code>. For example, if a subclass includes a 34 * notion of funds matching, the subclass implementation of this method 35 * may match some or all of the deposited amount at the time of deposit, 36 * effectively increasing the deposited amount. Or, if a subclass 37 * includes the notion of a deposit fee, the subclass's implementation of 38 * this method may charge that fee by decrementing it from the account at 39 * the time of deposit, effectively reducing the deposited amount. 40 * 41 * @param amount amount to deposit 42 * @throws ArithmeticException if requested deposit would cause the 43 * balance of this <code>Account</code> to exceed Long.MAX_VALUE. 44 * @throws IllegalArgumentException if requested deposit is less than 45 * or equal to zero. 46 */ 47 void deposit(long amount); 48 49 /** 50 * Gets the current balance of this <code>Account</code>. 51 * 52 * @return the current balance 53 */ 54 long getBalance(); 55 } 56 1 package com.artima.examples.account.ex4; 2 3 /** 4 * A generator of <code>OverdraftEvent</code>s. Classes that implement this 5 * interface manages the registration and unregistration of 6 * <code>OverdraftListener</code>s and the firing of 7 * <code>OverdraftEvent</code>s. 8 * 9 * @author Bill Venners 10 */ 11 public interface OverdraftEventGenerator { 12 13 /** 14 * Adds the specified overdraft listener to receive overdraft events. If 15 * <code>l</code> is <code>null</code>, no exception is thrown and no 16 * action is performed. If <code>l</code> is already registered as a 17 * listener, no action is performed. 18 * 19 * @param l the <code>OverdraftEventListener</code> to add 20 */ 21 void addOverdraftListener(OverdraftListener l); 22 23 /** 24 * Removes the specified overdraft listener so that it no longer receives 25 * overdraft events. This method performs no function, nor does it throw 26 * an exception, if the listener specified by the argument was not 27 * previously added to this component. If <code>l</code> is 28 * <code>null</code>, no exception is thrown and no action is performed. 29 * 30 * @param l the <code>OverdraftEventListener</code> to remove 31 */ 32 void removeOverdraftListener(OverdraftListener l); 33 } 1 package com.artima.examples.account.ex4; 2 3 /** 4 * Represents a bank account with overdraft protection. Instances of this 5 * class are instantiated with a specified maximum overdraft. If a client 6 * attempts to withdraw more than the current account balance, the bank may 7 * loan the amount in excess of the balance to the client. The overdraft 8 * maximum passed to an <code>OverdraftAccount</code>'s constructor is the 9 * maximum amount the bank will lend to the client in this manner. When a 10 * client makes a deposit, the bank will pay itself back first before 11 * increasing the account's balance. 12 * 13 * <p> 14 * Money is stored in this account in integral units. Clients can use this 15 * account to store any kind of value, such as money or points, etc. The 16 * meaning of the integral units stored in this account is a decision of the 17 * client that instantiates the account. The maximum amount of units that can 18 * be stored as the current balance of an <code>OverdraftAccount</code> is 19 * Long.MAX_VALUE. 20 */ 21 public class OverdraftAccount implements Account, OverdraftEventGenerator { 22 23 /** 24 * Helper back-end <code>BasicAccount</code> object 25 */ 26 private BasicAccount account = new BasicAccount(); 27 28 /** 29 * Helper back-end <code>OverdraftEventManager</code> object 30 */ 31 private OverdraftEventManager eventMan 32 = new OverdraftEventManager(); 33 34 /** 35 * The maximum amount the bank will loan to the client. 36 */ 37 private final long overdraftMax; 38 39 /** 40 * The current amount the bank has loaned to the client which has not yet 41 * been repaid. This value must at all times be greater than or equal to 42 * zero, and less than or equal to <code>overdraftMax</code>. If this 43 * value is greater than zero, then the balance of the helper 44 * <code>BasicAccount</code> (referenced from the <code>account</code> 45 * instance variable) must be exactly zero. 46 */ 47 private long overdraft; 48 49 /** 50 * Constructs a new <code>OverdraftAccount</code> with the passed 51 * overdraft maximum. 52 * 53 * @param overdraftMax the maximum amount the bank will loan to the 54 * client 55 */ 56 public OverdraftAccount(long overdraftMax) { 57 this.overdraftMax = overdraftMax; 58 } 59 60 /** 61 * Returns the current overdraft, the amount the bank has loaned to the 62 * client that has not yet been repaid. 63 * 64 * @return the current overdraft 65 */ 66 public long getOverdraft() { 67 return overdraft; 68 } 69 70 /** 71 * Returns the overdraft maximum, the maximum amount the bank will allow 72 * the client to owe it. For each instance of 73 * <code>OverdraftAccount</code>, the overdraft maximum is constant. 74 * 75 * @return the overdraft maximum 76 */ 77 public long getOverdraftMax() { 78 return overdraftMax; 79 } 80 81 /** 82 * Gets the current balance of this <code>OverdraftAccount</code>. 83 * 84 * @return the current balance 85 */ 86 public long getBalance() { 87 return account.getBalance(); 88 } 89 90 /** 91 * Withdraws the passed amount from this <code>OverdraftAccount</code>. 92 * If the passed amount is less than or equal to the current balance, all 93 * withdrawn funds will be taken from the balance, and the balance will 94 * be decremented by the passed amount. If the passed amount exceeds the 95 * current balance, the bank may loan the client the difference. The bank 96 * will make the loan only if the difference between the passed amount 97 * and the balance (the shortfall) is less than or equal to the available 98 * overdraft. The available overdraft is equal to the current overdraft 99 * (the amount already loaned to the client and not yet repaid), 100 * subtracted from the overdraft maximum, which is passed to the 101 * constructor of any <code>OverdraftAccount</code>. 102 * 103 * <p> 104 * If the passed amount is less than or equal to the current balance, the 105 * <code>withdraw</code> method decrements the current balance by the 106 * passed amount and returns the passed amount. If the passed amount is 107 * greater than the current balance, but the passed amount minus the 108 * current balance is less than or equal to the available overdraft, the 109 * <code>withdraw</code> method sets the current balance to zero, records 110 * the loan, and returns the requested amount. Otherwise, the passed 111 * amount minus the current balance exceeds the available overdraft, so 112 * the <code>withdraw</code> method throws 113 * <code>InsufficientFundsException</code>. 114 * 115 * Subclasses must withdraw at least the passed amount, but may 116 * effectively withdraw more. For example, if a subclass includes a 117 * notion of a withrawal fee, the subclass's implementation of this 118 * method may charge that fee by decrementing it from the account at the 119 * time of withdrawal. 120 * 121 * @param amount amount to withdraw 122 * @return amount withdrawn from the <code>OverdraftAccount</code> 123 * @throws InsufficientFundsException if the 124 * <code>OverdraftAccount</code> contains insufficient funds for the 125 * requested withdrawal 126 * @throws IllegalArgumentException if requested withdrawal amount is 127 * less than or equal to zero. 128 */ 129 public long withdraw(long amount) throws InsufficientFundsException { 130 131 if (amount <= 0) { 132 throw new IllegalArgumentException(); 133 } 134 135 long bal = account.getBalance(); 136 if (bal >= amount) { 137 138 // Balance has sufficient funds, so just take the 139 // money from the balance. 140 return account.withdraw(amount); 141 } 142 143 long shortfall = amount - bal; 144 long extraAvailable = overdraftMax - overdraft; 145 146 if (shortfall > extraAvailable) { 147 throw new InsufficientFundsException(shortfall 148 - extraAvailable); 149 } 150 overdraft += shortfall; 151 account.withdraw(amount - shortfall); 152 153 OverdraftEvent event = new OverdraftEvent(this, overdraft, 154 shortfall); 155 eventMan.fireOverdraftOccurred(event); 156 157 return amount; 158 } 159 160 /** 161 * Deposits the passed amount into the <code>OverdraftAccount</code>. If 162 * the current overdraft is zero, the balance will be increased by the 163 * passed amount. Otherwise, the bank will attempt to pay off the 164 * overdraft first, before increasing the current balance by the amount 165 * remaining after the overdraft is repaid, if any. 166 * 167 * <p> 168 * For example, if the balance is 0, the overdraft is 100, and the 169 * <code>deposit</code> method is invoked with a passed 170 * <code>amount</code> of 50, the bank would use all 50 of those monetary 171 * units to pay down the overdraft. The overdraft would be reduced to 50 172 * and the balance would remain at 0. If subsequently, the client 173 * deposits another 100 units, the bank would use 50 of those units to 174 * pay off the overdraft loan and direct the remaining 50 into the 175 * balance. The new overdraft would be 0 and the new balance would be 176 * 50. 177 * 178 * Subclasses may effectively deposit more or less than the passed amount 179 * into the <code>OverdraftAccount</code>. For example, if a subclass 180 * includes a notion of funds matching, the subclass implementation of 181 * this method may match some or all of the deposited amount at the time 182 * of deposit, effectively increasing the deposited amount. Or, if a 183 * subclass includes the notion of a deposit fee, the subclass's 184 * implementation of this method may charge that fee by decrementing it 185 * from the account at the time of deposit, effectively reducing the 186 * deposited amount. 187 * 188 * @param amount amount to deposit 189 * @throws ArithmeticException if requested deposit would cause the 190 * balance of this <code>OverdraftAccount</code> to exceed 191 * Long.MAX_VALUE. 192 * @throws IllegalArgumentException if requested withdrawal amount is 193 * less than or equal to zero. 194 */ 195 public void deposit(long amount) { 196 197 if (amount <= 0) { 198 throw new IllegalArgumentException(); 199 } 200 201 if (overdraft > 0) { 202 203 long amountRepaid = 0; 204 205 if (amount < overdraft) { 206 amountRepaid = amount; 207 overdraft -= amount; 208 } 209 else { 210 long diff = amount - overdraft; 211 amountRepaid = diff; 212 overdraft = 0; 213 account.deposit(diff); 214 } 215 216 OverdraftEvent event = new OverdraftEvent(this, overdraft, 217 amountRepaid); 218 eventMan.fireOverdraftRepaid(event); 219 } 220 else { 221 account.deposit(amount); 222 } 223 } 224 225 /** 226 * Adds the specified overdraft listener to receive overdraft events from 227 * this <code>OverdraftAccount</code>. If <code>l</code> is 228 * <code>null</code>, no exception is thrown and no action is performed. 229 * If <code>l</code> is already registered as a listener, no action is 230 * performed. 231 * 232 * @param l the <code>OverdraftEventListener</code> to add 233 */ 234 public void addOverdraftListener(OverdraftListener l) { 235 236 eventMan.addOverdraftListener(l); 237 } 238 239 /** 240 * Removes the specified overdraft listener so that it no longer receives 241 * overdraft events from this <code>OverdraftAccount</code>. This method 242 * performs no function, nor does it throw an exception, if the listener 243 * specified by the argument was not previously added to this component. 244 * If <code>l</code> is <code>null</code>, no exception is thrown and no 245 * action is performed. 246 * 247 * @param l the <code>OverdraftEventListener</code> to remove 248 */ 249 public void removeOverdraftListener(OverdraftListener l) { 250 251 eventMan.removeOverdraftListener(l); 252 } 253 } 1 package com.artima.examples.account.ex4; 2 3 /** 4 * Represents a bank account. Money is stored in this account in integral 5 * units. Clients can use this account to store any kind of value, such as 6 * money or points, etc. The meaning of the integral units stored in this 7 * account is a decision of the client that instantiates the account. The 8 * maximum amount of units that can be stored as the current balance of an 9 * <code>BasicAccount</code> is Long.MAX_VALUE. 10 */ 11 public class BasicAccount implements Account { 12 13 /** 14 * The current balance 15 */ 16 private long balance; 17 18 /** 19 * Withdraws exactly the passed amount from the 20 * <code>BasicAccount</code>. Subclasses must withdraw at least the 21 * passed amount, but may effectively withdraw more. For example, if a 22 * subclass includes a notion of a withrawal fee, the subclass's 23 * implementation of this method may charge that fee by decrementing it 24 * from the account at the time of withdrawal. 25 * 26 * @param amount amount to withdraw 27 * @return amount withdrawn from the <code>BasicAccount</code> 28 * @throws InsufficientFundsException if the <code>BasicAccount</code> 29 * contains insufficient funds for the requested withdrawal 30 * @throws IllegalArgumentException if the passed <code>amount</code> to 31 * withdraw is less than or equal to zero. 32 */ 33 public long withdraw(long amount) throws InsufficientFundsException { 34 35 if (amount <= 0) { 36 throw new IllegalArgumentException(); 37 } 38 39 if (amount > balance) { 40 throw new InsufficientFundsException(amount - balance); 41 } 42 43 balance -= amount; 44 return amount; 45 } 46 47 /** 48 * Deposits exactly the passed amount into the <code>BasicAccount</code>. 49 * Subclasses may effectively deposit more or less than the passed amount 50 * into the <code>BasicAccount</code>. For example, if a subclass 51 * includes a notion of funds matching, the subclass implementation of 52 * this method may match some or all of the deposited amount at the time 53 * of deposit, effectively increasing the deposited amount. Or, if a 54 * subclass includes the notion of a deposit fee, the subclass's 55 * implementation of this method may charge that fee by decrementing it 56 * from the account at the time of deposit, effectively reducing the 57 * deposited amount. 58 * 59 * @param amount amount to deposit 60 * @throws ArithmeticException if requested deposit would cause the 61 * balance of this <code>BasicAccount</code> to exceed 62 * Long.MAX_VALUE. 63 * @throws IllegalArgumentException if requested deposit is less than 64 * or equal to zero. 65 */ 66 public void deposit(long amount) { 67 68 if (amount <= 0) { 69 throw new IllegalArgumentException(); 70 } 71 72 long newBal = balance + amount; 73 74 if (newBal < 0) { 75 throw new ArithmeticException(); 76 } 77 78 balance = newBal; 79 } 80 81 /** 82 * Gets the current balance of this <code>BasicAccount</code>. 83 * 84 * @return the current balance 85 */ 86 public long getBalance() { 87 return balance; 88 } 89 } 90
interface
s so useful?interface
can be implemented in many ways:
interface
.
interface
sinterface
s to define large families or to say "What objects can do."
interface
s say "What objects are," without burdening subclasses with
any implementation
interface
s say what objects can do, no matter what
they are
interface
s say what you can can do to objects, no matter what
they are
interface
Collection
means: an object is a collection of other objects
interface
Comparable
means: an object can compare
itself with another object
interfaces
don't say what objects are
interface
Serializable
means: I can serialize an object
interface
s out of Thin Airinterface
s
where n is the number of methods |
interface
s when the family is so broad that
no default implementation makes sense
interface
s when thinking about
parameter and return types for method signatures
interface
s to define large families or to say "What objects can do."
interface
extension to decouple services or restrict the semantic contract.
List
adds void add(int, Object)
, Object get(int)
,
ListIterator listIterator()
, etc...
Set
doesn't declare any new methods compared to Collection
boolean add(Object)
:
Collection
- Ensures that this collection contains the specified element.
Set
- Adds the specified element to this set if it is not already present.
interface
extension to decouple services or restrict the semantic contract.
MouseAdapter
is a convenience implementation of MouseListener
Has emptymouseClicked()
,mousePressed()
, etc...
AbstractEntry
is a convenience implementation of Entry
Has default implementations ofequals()
,hashCode()
, andtoString()
AbstractCollection
, AbstractList
, AbstractSet
,
AbstractMap
, AbstractTableModel
, ...
interface
?
Canine
has one method, howl()
, that is abstract
Canine
is an abstract class, then expect subclasses like Dog
, Wolf
, etc...
Canine
is an interface, then could get implementations like Blender