|
|
|
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
|