The Artima Developer Community
Sponsored Link

Interface Design by Bill Venners
Use class extension to model permanent IS-A relationships

Advertisement

Interface Design | Contents | Previous | Next

As an example of when an interface isn't exactly what you want, use LinkMap and Map. Couldn't use Map because of RemoteException.

Class Extension


An OverdraftAccount Object

  1 package com.artima.examples.account.ex1;
  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 * As described in class <code>Account</code>, money is stored in
 16 * this account in integral units. Clients
 17 * can use this account to store any kind of value, such as money
 18 * or points, etc. The meaning of the integral units stored in
 19 * this account is a decision of the client that instantiates the
 20 * account. The maximum amount of units that can be stored as
 21 * the current balance of an <code>Account</code> is Long.MAX_VALUE.
 22 */
 23 public class OverdraftAccount extends Account {
 24
 25     /**
 26     * The maximum amount the bank will loan to the client.
 27     */
 28     private final long overdraftMax;
 29
 30     /**
 31     * The current amount the bank has loaned to the client
 32     * which has not yet been repaid. This must be zero to
 33     * overdraftMax.
 34     */
 35     private long overdraft;
 36
 37     /**
 38     * Constructs a new <code>OverdraftAccount</code> with the
 39     * passed <code>overdraftMax</code>.
 40     *
 41     * @param overdraftMax the maximum amount the bank will loan
 42     *     to the client
 43     */
 44     public OverdraftAccount(long overdraftMax) {
 45         this.overdraftMax = overdraftMax;
 46     }
 47
 48     /**
 49     * Returns the current overdraft, the amount the bank has
 50     * loaned to the client that has not yet been repaid.
 51     *
 52     * @returns the current overdraft
 53     */
 54     public long getOverdraft() {
 55         return overdraft;
 56     }
 57
 58     /**
 59     * Returns the overdraft maximum, the maximum amount the
 60     * bank will allow the client to owe it. For each instance
 61     * of <code>OverdraftAccount</code>, the overdraft maximum
 62     * is constant.
 63     *
 64     * @returns the overdraft maximum
 65     */
 66     public long getOverdraftMax() {
 67         return overdraftMax;
 68     }
 69
 70     /**
 71     * Withdraws exactly the passed amount from the
 72     * <code>Account</code>. If the passed amount is
 73     * less than or equal to the current balance, all withdrawn
 74     * funds will be taken from the balance, and the balance
 75     * will be decremented by the passed amount. If the passed amount
 76     * exceeds the current balance, the bank may loan the client the
 77     * difference. The bank will make the loan only if the difference
 78     * between the passed amount and the balance is less than or equal to
 79     * the available overdraft. The available overdraft is equal to
 80     * the current overdraft (the amount already loaned to the client and
 81     * not yet repaid), subtracted from the overdraft maximum, which
 82     * is passed to the constructor of any <code>OverdraftAccount</code>.
 83     *
 84     * <p>
 85     * If the passed amount less the current balance is less than or equal
 86     * to the available overdraft, the <code>withdraw</code> method returns
 87     * the requested amount, sets the current balance to zero, and records
 88     * the loan. Otherwise, if the passed amount less the current balance
 89     * exceeds the available overdraft, the <code>withdraw</code> method throws
 90     * <code>InsufficientFundsException</code>.
 91     *
 92     * @param amount amount to withdraw
 93     * @returns amount withdrawn from the <code>Account</code>
 94     * @throws InsufficientFundsException if the <code>Account</code>
 95     *     contains insufficient funds for the requested withdrawal
 96     */
 97     public long withdraw(long amount)
 98         throws InsufficientFundsException {
 99
100         long balance = getBalance();
101         if (balance >= amount) {
102
103             // Balance has sufficient funds, just take the
104             // money from the balance.
105             balance -= amount;
106             return amount;
107         }
108
109         long shortfall = amount - balance;
110         long extraAvailable = overdraftMax - overdraft;
111
112         if (shortfall > extraAvailable) {
113             throw new InsufficientFundsException(shortfall - extraAvailable);
114         }
115         overdraft += shortfall;
116         super.withdraw(amount - shortfall);
117
118         return amount;
119     }
120
121     /**
122     * Deposits exactly the passed amount into the <code>Account</code>.
123     * If the current overdraft is zero, the balance will be increased
124     * by the passed amount. Otherwise, the bank will attempt to pay
125     * off the overdraft first, before increasing the current balance
126     * by the amount remaining after the overdraft is repaid, if any.
127     *
128     * <p>
129     * For example, if the balance is 200, the overdraft is 100, and the
130     * <code>deposit</code> method is invoked with a passed <code>amount</code>
131     * of 50, the bank would use all 50 of those monetary units to pay down
132     * the overdraft. The overdraft would be reduced to 50 and the balance would
133     * remain at 200. If subsequently, the client deposits another 100 units,
134     * the bank would use 50 of those units to pay off the overdraft loan and
135     * direct the remaining 50 into the balance. The new overdraft would
136     * be 0 and the new balance would be 250.
137     *
138     * @param amount amount to deposit
139     * @throws ArithmeticException if requested deposit would cause the
140     *     balance of this <code>Account</code> to exceed Long.MAX_VALUE.
141     */
142     public void deposit(long amount) {
143         if (overdraft > 0) {
144             if (amount < overdraft) {
145                 overdraft -= amount;
146             }
147             else {
148                 long diff = amount - overdraft;
149                 overdraft = 0;
150                 super.deposit(diff);
151             }
152         }
153         else {
154             super.deposit(amount);
155         }
156     }
157 }

Roles and Attributes


State and Class


How do You Decide?

Wouldn't want to say: Overdraft100Account, Overdraft500Account, and Overdraft1000Account if there were just three legal overdraft maxes. Just use OverdraftAccount that takes a max. And either allow client to establish legal values for overdraft (other than negative), or check at constructor for legal values.


Why IS-A?


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use