From 2008精选 |
Refactoring, a First Example
這是一個影片出租店用的程式,計算每位顧客的消費金額並列
印報表(statement)。操作者告訴程式:顧客租了哪些影片、租期多長,程式便
根據租賃時間和影片類型算出費用。影片分為三類:普通片、兒童片和新片。除
了計算費用,還要為常客計算點數;點數會隨著「租片種類是否為新片」而有不
同。
我以數個classes 表現這個例子?的元素。圖1.1 是一張UML class diagram(類別
圖),用以顯示這些classes。
1
//
movie.cpp : Defines the entry point for the console application.
2 //
3 #include < string >
4 #include < vector >
5 #include < iostream >
6
7 using namespace std;
8
9
10 // Refactoring, a First Example, step1, (~p5)
11
12 class Movie {
13public:
14 enum TYPE {
15 REGULAR,
16 NEW_RELEASE,
17 CHILDRENS
18 };
19
20private:
21 string _title; //movie name
22 int _priceCode; //price code
23
24public:
25 //default construtor for `Rental::Rental(Movie, int)'
26 Movie() {
27 _title = "unname";
28 _priceCode = 0;
29 }
30 Movie(string title, int priceCode){
31 _title = title;
32 _priceCode = priceCode;
33 }
34
35 int getPriceCode() {
36 return _priceCode;
37 }
38
39 void setPriceCode(int arg) {
40 _priceCode = arg;
41 }
42
43 string getTitle() {
44 return _title;
45 }
46} ;
47
48 class Rental {
49private:
50 Movie _movie;
51 int _daysRented;
52
53public:
54 Rental(Movie movie, int daysRented) {
55 _movie = movie;
56 _daysRented = daysRented;
57 }
58
59 int getDaysRented() {
60 return _daysRented;
61 }
62
63 Movie getMovie() {
64 return _movie;
65 }
66} ;
67
68 typedef vector < Rental > Vector;
69 typedef vector < Rental > ::iterator Reniter;
70
71 class Customer {
72private:
73 string _name;
74 Vector _rentals;
75
76public:
77 Customer(string name) {
78 _name = name;
79 }
80
81 void addRental(Rental arg) {
82 _rentals.push_back(arg);
83 }
84
85 string getName() {
86 return _name;
87 }
88
89 string statement() {
90 double totalAmount = 0;
91 int frequentRenterPoints = 0;
92 Reniter iter;
93 char amount[32];
94 string result = string("Rental Record for ") + getName() + string("\n");
95
96 for (iter = _rentals.begin(); iter != _rentals.end(); ++ iter) {
97 double thisAmount = 0;
98 Rental each = *iter;
99
100 //determine amounts for each line
101 switch(each.getMovie().getPriceCode()){
102 case Movie::REGULAR:
103 thisAmount += 2;
104 if(each.getDaysRented()>2)
105 thisAmount += (each.getDaysRented()-2)*1.5;
106 break;
107
108 case Movie::NEW_RELEASE:
109 thisAmount += each.getDaysRented()*3;
110 break;
111
112 case Movie::CHILDRENS:
113 thisAmount += 1.5;
114 if(each.getDaysRented()>3)
115 thisAmount += (each.getDaysRented()-3)*1.5;
116 break;
117 }
118
119 // add frequent renter points?
120 frequentRenterPoints ++;
121 // add bonus for a two day new release rental
122 if ((each.getMovie().getPriceCode() == Movie::NEW_RELEASE) &&
123 each.getDaysRented() > 1)
124 frequentRenterPoints ++;
125
126 // show figures for this rental?
127 snprintf(amount, 32,"%f\n",thisAmount);
128 result += string("\t") + each.getMovie().getTitle() + string("\t") +
129 string(amount);
130 totalAmount += thisAmount;
131 }
132
133 // add footer lines?
134 snprintf(amount, 32, "%f\n",totalAmount);
135 result += string("Amount owed is ") + string(amount);
136 snprintf(amount, 32,"%d",frequentRenterPoints);
137 result += string("You earned ") + string(amount) +
138 string(" frequent renter points");
139 return result;
140 }
141} ;
142
143 int main( int argc, char * argv[])
144 {
145 cout<<"Refactoring, a First Example, step1"<<endl;
146
147 Movie m1 = Movie("Seven", Movie::NEW_RELEASE);
148 Movie m2 = Movie("Terminator", Movie::REGULAR);
149 Movie m3 = Movie("Star Trek", Movie::CHILDRENS);
150
151 Rental r1 = Rental(m1, 4);
152 Rental r2 = Rental(m1, 2);
153 Rental r3 = Rental(m3, 7);
154 Rental r4 = Rental(m2, 5);
155 Rental r5 = Rental(m3, 3);
156
157 Customer c1 = Customer("jjhou");
158 c1.addRental(r1);
159 c1.addRental(r4);
160
161 Customer c2 = Customer("gigix");
162 c2.addRental(r1);
163 c2.addRental(r3);
164 c2.addRental(r2);
165
166 Customer c3 = Customer("jiangtao");
167 c3.addRental(r3);
168 c3.addRental(r5);
169
170 Customer c4 = Customer("yeka");
171 c4.addRental(r2);
172 c4.addRental(r3);
173 c4.addRental(r5);
174
175 cout <<c1.statement() <<endl;
176 cout <<c2.statement() <<endl;
177 cout <<c3.statement() <<endl;
178 cout <<c4.statement() <<endl;
179
180 return 0;
181}
182
183
2 //
3 #include < string >
4 #include < vector >
5 #include < iostream >
6
7 using namespace std;
8
9
10 // Refactoring, a First Example, step1, (~p5)
11
12 class Movie {
13public:
14 enum TYPE {
15 REGULAR,
16 NEW_RELEASE,
17 CHILDRENS
18 };
19
20private:
21 string _title; //movie name
22 int _priceCode; //price code
23
24public:
25 //default construtor for `Rental::Rental(Movie, int)'
26 Movie() {
27 _title = "unname";
28 _priceCode = 0;
29 }
30 Movie(string title, int priceCode){
31 _title = title;
32 _priceCode = priceCode;
33 }
34
35 int getPriceCode() {
36 return _priceCode;
37 }
38
39 void setPriceCode(int arg) {
40 _priceCode = arg;
41 }
42
43 string getTitle() {
44 return _title;
45 }
46} ;
47
48 class Rental {
49private:
50 Movie _movie;
51 int _daysRented;
52
53public:
54 Rental(Movie movie, int daysRented) {
55 _movie = movie;
56 _daysRented = daysRented;
57 }
58
59 int getDaysRented() {
60 return _daysRented;
61 }
62
63 Movie getMovie() {
64 return _movie;
65 }
66} ;
67
68 typedef vector < Rental > Vector;
69 typedef vector < Rental > ::iterator Reniter;
70
71 class Customer {
72private:
73 string _name;
74 Vector _rentals;
75
76public:
77 Customer(string name) {
78 _name = name;
79 }
80
81 void addRental(Rental arg) {
82 _rentals.push_back(arg);
83 }
84
85 string getName() {
86 return _name;
87 }
88
89 string statement() {
90 double totalAmount = 0;
91 int frequentRenterPoints = 0;
92 Reniter iter;
93 char amount[32];
94 string result = string("Rental Record for ") + getName() + string("\n");
95
96 for (iter = _rentals.begin(); iter != _rentals.end(); ++ iter) {
97 double thisAmount = 0;
98 Rental each = *iter;
99
100 //determine amounts for each line
101 switch(each.getMovie().getPriceCode()){
102 case Movie::REGULAR:
103 thisAmount += 2;
104 if(each.getDaysRented()>2)
105 thisAmount += (each.getDaysRented()-2)*1.5;
106 break;
107
108 case Movie::NEW_RELEASE:
109 thisAmount += each.getDaysRented()*3;
110 break;
111
112 case Movie::CHILDRENS:
113 thisAmount += 1.5;
114 if(each.getDaysRented()>3)
115 thisAmount += (each.getDaysRented()-3)*1.5;
116 break;
117 }
118
119 // add frequent renter points?
120 frequentRenterPoints ++;
121 // add bonus for a two day new release rental
122 if ((each.getMovie().getPriceCode() == Movie::NEW_RELEASE) &&
123 each.getDaysRented() > 1)
124 frequentRenterPoints ++;
125
126 // show figures for this rental?
127 snprintf(amount, 32,"%f\n",thisAmount);
128 result += string("\t") + each.getMovie().getTitle() + string("\t") +
129 string(amount);
130 totalAmount += thisAmount;
131 }
132
133 // add footer lines?
134 snprintf(amount, 32, "%f\n",totalAmount);
135 result += string("Amount owed is ") + string(amount);
136 snprintf(amount, 32,"%d",frequentRenterPoints);
137 result += string("You earned ") + string(amount) +
138 string(" frequent renter points");
139 return result;
140 }
141} ;
142
143 int main( int argc, char * argv[])
144 {
145 cout<<"Refactoring, a First Example, step1"<<endl;
146
147 Movie m1 = Movie("Seven", Movie::NEW_RELEASE);
148 Movie m2 = Movie("Terminator", Movie::REGULAR);
149 Movie m3 = Movie("Star Trek", Movie::CHILDRENS);
150
151 Rental r1 = Rental(m1, 4);
152 Rental r2 = Rental(m1, 2);
153 Rental r3 = Rental(m3, 7);
154 Rental r4 = Rental(m2, 5);
155 Rental r5 = Rental(m3, 3);
156
157 Customer c1 = Customer("jjhou");
158 c1.addRental(r1);
159 c1.addRental(r4);
160
161 Customer c2 = Customer("gigix");
162 c2.addRental(r1);
163 c2.addRental(r3);
164 c2.addRental(r2);
165
166 Customer c3 = Customer("jiangtao");
167 c3.addRental(r3);
168 c3.addRental(r5);
169
170 Customer c4 = Customer("yeka");
171 c4.addRental(r2);
172 c4.addRental(r3);
173 c4.addRental(r5);
174
175 cout <<c1.statement() <<endl;
176 cout <<c2.statement() <<endl;
177 cout <<c3.statement() <<endl;
178 cout <<c4.statement() <<endl;
179
180 return 0;
181}
182
183
1
//
movie-ref.cpp : Defines the entry point for the console application.
2 //
3 #include < string >
4 #include < vector >
5 #include < iostream >
6
7 using namespace std;
8 // Refactoring, a First Example, step7, (~p52)
9
10 enum TYPE
11 {
12 REGULAR,
13 NEW_RELEASE,
14 CHILDRENS
15} ;
16
17 class Price
18 {
19public:
20 virtual int getPriceCode () = 0;
21 virtual double getCharge (int daysRented) = 0;
22
23 int getFrequentRenterPoints (int daysRented)
24 {
25 return 1;
26 }
27
28} ;
29
30 class ChildrensPrice: public Price
31 {
32public:
33 int getPriceCode ()
34 {
35 return CHILDRENS;
36 }
37
38 double getCharge (int daysRented)
39 {
40 double result = 1.5;
41 if (daysRented > 3)
42 result += (daysRented - 3) * 1.5;
43 return result;
44 }
45} ;
46
47 class NewReleasePrice: public Price
48 {
49public:
50 int getPriceCode ()
51 {
52 return NEW_RELEASE;
53 }
54
55 double getCharge (int daysRented)
56 {
57 return daysRented * 3;
58 }
59
60 int getFrequentRenterPoints (int daysRented)
61 {
62 return (daysRented > 1) ? 2 : 1;
63 }
64} ;
65
66 class RegularPrice: public Price
67 {
68public:
69 int getPriceCode ()
70 {
71 return REGULAR;
72 }
73
74 double getCharge (int daysRented)
75 {
76 double result = 2;
77 if (daysRented > 2)
78 result += (daysRented - 2) * 1.5;
79 return result;
80 }
81} ;
82
83 class Movie
84 {
85private:
86 string _title; //movie name
87 Price *_price; //price code
88
89public:
90 //default construtor for `Rental::Rental(Movie&, int)'
91 Movie ()
92 {
93 _title = "unname";
94 setPriceCode (0);
95 }
96
97 Movie (string title, int priceCode)
98 {
99 _title = title;
100 setPriceCode (priceCode);
101 }
102
103 Movie (const Movie& movie)
104 {
105 _title = movie._title;
106 setPriceCode (movie._price->getPriceCode());
107 }
108
109 ~Movie()
110 {
111 delete _price;
112 }
113
114 int getPriceCode ()
115 {
116 return _price->getPriceCode ();
117 }
118
119 void setPriceCode (int arg)
120 {
121 switch (arg)
122 {
123 case REGULAR:
124 _price = new RegularPrice ();
125 break;
126 case CHILDRENS:
127 _price = new ChildrensPrice ();
128 break;
129 case NEW_RELEASE:
130 _price = new NewReleasePrice ();
131 break;
132 default:
133 cout << "Incorrect Price Code" << endl;
134 break;
135 }
136 }
137
138 string getTitle ()
139 {
140 return _title;
141 }
142
143 double getCharge (int daysRented)
144 {
145 return _price->getCharge (daysRented);
146 }
147
148 int getFrequentRenterPoints (int daysRented)
149 {
150 return _price->getFrequentRenterPoints (daysRented);
151 }
152} ;
153
154 class Rental
155 {
156private:
157 Movie _movie;
158 int _daysRented;
159
160public:
161 Rental (Movie& movie, int daysRented)
162 {
163 _movie = movie;
164 _daysRented = daysRented;
165 }
166
167 int getDaysRented ()
168 {
169 return _daysRented;
170 }
171
172 Movie getMovie ()
173 {
174 return _movie;
175 }
176
177 double getCharge ()
178 {
179 return _movie.getCharge (_daysRented);
180 }
181
182 int getFrequentRenterPoints ()
183 {
184 return _movie.getFrequentRenterPoints (_daysRented);
185 }
186} ;
187
188 typedef vector < Rental > Vector;
189 typedef vector < Rental > ::iterator Reniter;
190
191 class Customer
192 {
193private:
194 string _name;
195 Vector _rentals;
196
197public:
198 Customer (string name)
199 {
200 _name = name;
201 }
202
203 void addRental (Rental& arg)
204 {
205 _rentals.push_back (arg);
206 }
207
208 string getName ()
209 {
210 return _name;
211 }
212
213 string statement ()
214 {
215 Reniter iter;
216 char amount[32];
217 string result =
218 string ("Rental Record for ") + getName () + string ("\n");
219
220 for (iter = _rentals.begin (); iter != _rentals.end (); ++iter)
221 {
222 Rental each = *iter;
223 // show figures for this rental
224 snprintf (amount, 32, "%f\n", each.getCharge ());
225 result += string ("\t") + each.getMovie ().getTitle ()
226 + string ("\t") + string (amount);
227 }
228 // add footer lines
229 snprintf (amount, 32, "%f\n", getTotalCharge ());
230 result += string ("Amount owed is ") + string (amount);
231 snprintf (amount, 32, "%d", getTotalFrequentRenterPoints ());
232 result += string ("You earned ") + string (amount) +
233 string (" frequent renter points");
234 return result;
235 }
236
237 string htmlStatement ()
238 {
239 Reniter iter;
240 char amount[32];
241 string result =
242 string ("<H1>Rentals for <EM>") + getName () +
243 string ("</EM></H1><P>\n");
244
245 for (iter = _rentals.begin (); iter != _rentals.end (); ++iter)
246 {
247 Rental each = *iter;
248 // show figures for this rental
249 snprintf (amount, 32, "%f<BR>\n", each.getCharge ());
250 result += each.getMovie ().getTitle () + string (":") + string (amount);
251 }
252
253 // add footer lines?
254 snprintf (amount, 32, "%f</EM><P>\n", getTotalCharge ());
255 result += string ("<P>You owe <EM>") + string (amount);
256 snprintf (amount, 32, "%d</EM> frequent renter points<P>",
257 getTotalFrequentRenterPoints ());
258 result += string ("On this rental you earned <EM>") + string (amount);
259 return result;
260 }
261
262 int getTotalFrequentRenterPoints ()
263 {
264 int result = 0;
265 Reniter iter;
266 for (iter = _rentals.begin (); iter != _rentals.end (); ++iter)
267 {
268 Rental each = *iter;
269 result += each.getFrequentRenterPoints ();
270 }
271 return result;
272 }
273
274 double getTotalCharge ()
275 {
276 double result = 0;
277 Reniter iter;
278 for (iter = _rentals.begin (); iter != _rentals.end (); ++iter)
279 {
280 Rental each = *iter;
281 result += each.getCharge ();
282 }
283 return result;
284 }
285
286} ;
287
288 int
289 main ( int argc, char * argv[])
290 {
291 cout << "Refactoring, a First Example, step7" << endl;
292
293 Movie m1 = Movie ("Seven", NEW_RELEASE);
294 Movie m2 = Movie ("Terminator", REGULAR);
295 Movie m3 = Movie ("Star Trek", CHILDRENS);
296
297 Rental r1 = Rental (m1, 4);
298 Rental r2 = Rental (m1, 2);
299 Rental r3 = Rental (m3, 7);
300 Rental r4 = Rental (m2, 5);
301 Rental r5 = Rental (m3, 3);
302
303 Customer c1 = Customer ("jjhou");
304 c1.addRental (r1);
305 c1.addRental (r4);
306
307 Customer c2 = Customer ("gigix");
308 c2.addRental (r1);
309 c2.addRental (r3);
310 c2.addRental (r2);
311
312 Customer c3 = Customer ("jiangtao");
313 c3.addRental (r3);
314 c3.addRental (r5);
315
316 Customer c4 = Customer ("yeka");
317 c4.addRental (r2);
318 c4.addRental (r3);
319 c4.addRental (r5);
320
321 cout << c1.statement () << endl;
322 cout << c2.statement () << endl;
323 cout << c3.statement () << endl;
324 cout << c4.statement () << endl;
325
326 return 0;
327}
328
329
2 //
3 #include < string >
4 #include < vector >
5 #include < iostream >
6
7 using namespace std;
8 // Refactoring, a First Example, step7, (~p52)
9
10 enum TYPE
11 {
12 REGULAR,
13 NEW_RELEASE,
14 CHILDRENS
15} ;
16
17 class Price
18 {
19public:
20 virtual int getPriceCode () = 0;
21 virtual double getCharge (int daysRented) = 0;
22
23 int getFrequentRenterPoints (int daysRented)
24 {
25 return 1;
26 }
27
28} ;
29
30 class ChildrensPrice: public Price
31 {
32public:
33 int getPriceCode ()
34 {
35 return CHILDRENS;
36 }
37
38 double getCharge (int daysRented)
39 {
40 double result = 1.5;
41 if (daysRented > 3)
42 result += (daysRented - 3) * 1.5;
43 return result;
44 }
45} ;
46
47 class NewReleasePrice: public Price
48 {
49public:
50 int getPriceCode ()
51 {
52 return NEW_RELEASE;
53 }
54
55 double getCharge (int daysRented)
56 {
57 return daysRented * 3;
58 }
59
60 int getFrequentRenterPoints (int daysRented)
61 {
62 return (daysRented > 1) ? 2 : 1;
63 }
64} ;
65
66 class RegularPrice: public Price
67 {
68public:
69 int getPriceCode ()
70 {
71 return REGULAR;
72 }
73
74 double getCharge (int daysRented)
75 {
76 double result = 2;
77 if (daysRented > 2)
78 result += (daysRented - 2) * 1.5;
79 return result;
80 }
81} ;
82
83 class Movie
84 {
85private:
86 string _title; //movie name
87 Price *_price; //price code
88
89public:
90 //default construtor for `Rental::Rental(Movie&, int)'
91 Movie ()
92 {
93 _title = "unname";
94 setPriceCode (0);
95 }
96
97 Movie (string title, int priceCode)
98 {
99 _title = title;
100 setPriceCode (priceCode);
101 }
102
103 Movie (const Movie& movie)
104 {
105 _title = movie._title;
106 setPriceCode (movie._price->getPriceCode());
107 }
108
109 ~Movie()
110 {
111 delete _price;
112 }
113
114 int getPriceCode ()
115 {
116 return _price->getPriceCode ();
117 }
118
119 void setPriceCode (int arg)
120 {
121 switch (arg)
122 {
123 case REGULAR:
124 _price = new RegularPrice ();
125 break;
126 case CHILDRENS:
127 _price = new ChildrensPrice ();
128 break;
129 case NEW_RELEASE:
130 _price = new NewReleasePrice ();
131 break;
132 default:
133 cout << "Incorrect Price Code" << endl;
134 break;
135 }
136 }
137
138 string getTitle ()
139 {
140 return _title;
141 }
142
143 double getCharge (int daysRented)
144 {
145 return _price->getCharge (daysRented);
146 }
147
148 int getFrequentRenterPoints (int daysRented)
149 {
150 return _price->getFrequentRenterPoints (daysRented);
151 }
152} ;
153
154 class Rental
155 {
156private:
157 Movie _movie;
158 int _daysRented;
159
160public:
161 Rental (Movie& movie, int daysRented)
162 {
163 _movie = movie;
164 _daysRented = daysRented;
165 }
166
167 int getDaysRented ()
168 {
169 return _daysRented;
170 }
171
172 Movie getMovie ()
173 {
174 return _movie;
175 }
176
177 double getCharge ()
178 {
179 return _movie.getCharge (_daysRented);
180 }
181
182 int getFrequentRenterPoints ()
183 {
184 return _movie.getFrequentRenterPoints (_daysRented);
185 }
186} ;
187
188 typedef vector < Rental > Vector;
189 typedef vector < Rental > ::iterator Reniter;
190
191 class Customer
192 {
193private:
194 string _name;
195 Vector _rentals;
196
197public:
198 Customer (string name)
199 {
200 _name = name;
201 }
202
203 void addRental (Rental& arg)
204 {
205 _rentals.push_back (arg);
206 }
207
208 string getName ()
209 {
210 return _name;
211 }
212
213 string statement ()
214 {
215 Reniter iter;
216 char amount[32];
217 string result =
218 string ("Rental Record for ") + getName () + string ("\n");
219
220 for (iter = _rentals.begin (); iter != _rentals.end (); ++iter)
221 {
222 Rental each = *iter;
223 // show figures for this rental
224 snprintf (amount, 32, "%f\n", each.getCharge ());
225 result += string ("\t") + each.getMovie ().getTitle ()
226 + string ("\t") + string (amount);
227 }
228 // add footer lines
229 snprintf (amount, 32, "%f\n", getTotalCharge ());
230 result += string ("Amount owed is ") + string (amount);
231 snprintf (amount, 32, "%d", getTotalFrequentRenterPoints ());
232 result += string ("You earned ") + string (amount) +
233 string (" frequent renter points");
234 return result;
235 }
236
237 string htmlStatement ()
238 {
239 Reniter iter;
240 char amount[32];
241 string result =
242 string ("<H1>Rentals for <EM>") + getName () +
243 string ("</EM></H1><P>\n");
244
245 for (iter = _rentals.begin (); iter != _rentals.end (); ++iter)
246 {
247 Rental each = *iter;
248 // show figures for this rental
249 snprintf (amount, 32, "%f<BR>\n", each.getCharge ());
250 result += each.getMovie ().getTitle () + string (":") + string (amount);
251 }
252
253 // add footer lines?
254 snprintf (amount, 32, "%f</EM><P>\n", getTotalCharge ());
255 result += string ("<P>You owe <EM>") + string (amount);
256 snprintf (amount, 32, "%d</EM> frequent renter points<P>",
257 getTotalFrequentRenterPoints ());
258 result += string ("On this rental you earned <EM>") + string (amount);
259 return result;
260 }
261
262 int getTotalFrequentRenterPoints ()
263 {
264 int result = 0;
265 Reniter iter;
266 for (iter = _rentals.begin (); iter != _rentals.end (); ++iter)
267 {
268 Rental each = *iter;
269 result += each.getFrequentRenterPoints ();
270 }
271 return result;
272 }
273
274 double getTotalCharge ()
275 {
276 double result = 0;
277 Reniter iter;
278 for (iter = _rentals.begin (); iter != _rentals.end (); ++iter)
279 {
280 Rental each = *iter;
281 result += each.getCharge ();
282 }
283 return result;
284 }
285
286} ;
287
288 int
289 main ( int argc, char * argv[])
290 {
291 cout << "Refactoring, a First Example, step7" << endl;
292
293 Movie m1 = Movie ("Seven", NEW_RELEASE);
294 Movie m2 = Movie ("Terminator", REGULAR);
295 Movie m3 = Movie ("Star Trek", CHILDRENS);
296
297 Rental r1 = Rental (m1, 4);
298 Rental r2 = Rental (m1, 2);
299 Rental r3 = Rental (m3, 7);
300 Rental r4 = Rental (m2, 5);
301 Rental r5 = Rental (m3, 3);
302
303 Customer c1 = Customer ("jjhou");
304 c1.addRental (r1);
305 c1.addRental (r4);
306
307 Customer c2 = Customer ("gigix");
308 c2.addRental (r1);
309 c2.addRental (r3);
310 c2.addRental (r2);
311
312 Customer c3 = Customer ("jiangtao");
313 c3.addRental (r3);
314 c3.addRental (r5);
315
316 Customer c4 = Customer ("yeka");
317 c4.addRental (r2);
318 c4.addRental (r3);
319 c4.addRental (r5);
320
321 cout << c1.statement () << endl;
322 cout << c2.statement () << endl;
323 cout << c3.statement () << endl;
324 cout << c4.statement () << endl;
325
326 return 0;
327}
328
329
結語
這是一個簡單的例子,但我希望它能讓你對於「重構是什麼樣子」有一點感覺。
例如我已經示範了數個重構準則,包括Extract Method(110)、Move Method(142)、
Replace Conditional with Polymorphism(255)、Self Encapsulate Field(171) 、
Replace Type Code with State/Strategy(227)。所有這些重構行為都使責任的分
配更合理,程式碼的維護更輕鬆。重構後的程式風格,將十分不同於程序式
(procedural)風格,後者也許是某些人習慣的風格。不過一旦你習慣了這種重構
後的風格,就很難再回到(再滿足於)結構化風格了。
這個例子給你的最重要一課是「重構的節奏」:測試、小修改、測試、小修改、
測試、小修改…。正是這種節奏讓重構得以快速而安全地前進。