为大家提供一个小小的思路

SalesFormatter接口

1
2
3
4
5
package GourmetCoffee;

public interface SalesFormatter {
public abstract String formatSales(Sales sales);
}

PlainTextSalesFormatter类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package GourmetCoffee;

import java.util.ArrayList;
import java.io.*;

public class PlainTextSalesFormatter implements SalesFormatter{

private static PlainTextSalesFormatter singletonInstance;

private PlainTextSalesFormatter()
{

}

public static PlainTextSalesFormatter getSingletonInstance()
{

if(singletonInstance==null)
{
return singletonInstance=new PlainTextSalesFormatter();
}

return singletonInstance;
}


private ArrayList<String> info=new ArrayList<String>();
public String formatSales(Sales sales)
{
int k=1;

for(Order order:sales)
{
info.add("------------------------\n");
info.add("Order "+k+"\n\n");
for(OrderItem orderItem:order)
{
info.add(orderItem.getQuantity()+" "+orderItem.getProduct().getCode()+" "+orderItem.getProduct().getPrice()+"\n\n");
}
info.add("Total = "+order.getTotalCost()+"\n");
k++;

}
String res="";
for(int i=0;i<info.size();i++)
{
res+=info.get(i);
}
return res;
}
}

HTMLSalesFormatter类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package GourmetCoffee;
import java.util.*;
public class HTMLSalesFormatter implements SalesFormatter{

private static HTMLSalesFormatter singletonInstance;

private HTMLSalesFormatter()
{

}
public static HTMLSalesFormatter getSingletonInstance()
{
if(singletonInstance==null)
{
return singletonInstance=new HTMLSalesFormatter();
}

return singletonInstance;

}
private ArrayList<String> output=new ArrayList<String>();
public String formatSales(Sales sales)
{
output.add("<html>\n"+" <body>\n"+" <center><h2>Orders</h2></center>\n");

for(Order order:sales)
{
output.add(" <hr>\n"+" <h4>Total = "+order.getTotalCost()+"</h4>\n");

for(OrderItem orderItem:order)
{
output.add(" <p>\n"+" <b>code:</b> "+orderItem.getProduct().getCode()+"<br>\n");
output.add(" <b>quantity:</b> "+orderItem.getQuantity()+"<br>\n");
output.add(" <b>price:</b> "+orderItem.getProduct().getPrice()+"\n </p>\n");
}
}
output.add(" </body>\n"+"</html>");
String res="";
for(int i=0;i<output.size();i++)
{
res+=output.get(i);
}
return res;
}
}

XMLSalesFormatter类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package GourmetCoffee;
import java.util.ArrayList;
public class XMLSalesFormatter implements SalesFormatter{

private static XMLSalesFormatter singletonInstance;

private XMLSalesFormatter()
{

}
public static XMLSalesFormatter getSingletonInstance()
{
if(singletonInstance==null)
{
return singletonInstance=new XMLSalesFormatter();
}

return singletonInstance;
}
private ArrayList<String> output=new ArrayList<String>();
public String formatSales(Sales sales) {
output.add("<Sales>\n");
for(Order order: sales)
{
output.add(" <Order total=\""+ order.getTotalCost()+"\">\n");
for(OrderItem orderitem: order)
{
output.add(" <OrderItem quantity=\""+ orderitem.getQuantity()+"\" price=\""+orderitem.getProduct()+"\">code1</OrderItem>\n");
}
output.add(" </Order>\n");
}
output.add("</Sales>\n");
String res = "" ;
for(int i=0;i<output.size();i++) {
res+=output.get(i);
}
return res;
}
}

GourmetCoffee类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
package GourmetCoffee;
import java.io.*;
import java.util.*;
//import java.text.*;

/**
* This class implements a gourmet coffee system.
*
* @author author name
* @version 1.1.0
* @see Product
* @see Coffee
* @see CoffeeBrewer
* @see Catalog
* @see OrderItem
* @see Order
* @see SalesFormatter
* @see PlainTextSalesFormatter
* @see HTMLSalesFormatter
* @see XMLSalesFormatter
*/
public class GourmetCoffee {

private static BufferedReader stdIn =
new BufferedReader(new InputStreamReader(System.in));
private static PrintWriter stdOut = new PrintWriter(System.out, true);
private static PrintWriter stdErr = new PrintWriter(System.err, true);

private Sales sales;

private SalesFormatter salesFormatter;

/**
* Loads data into the catalog and starts the application.
*
* @param args String arguments. Not used.
* @throws IOException if there are errors in the input.
*/
public static void main(String[] args) throws IOException {

GourmetCoffee application = new GourmetCoffee();
application.run();

}

/**
* Constructs a <code>GourmetCoffee</code> object and
* initializes the catalog and sales data.
*
* @param initialCatalog a product catalog
*/
private GourmetCoffee() {

this.sales = new Sales();
this.salesFormatter =
PlainTextSalesFormatter.getSingletonInstance();

loadSales(loadCatalog());
}

/**
* Creates an empty catalog and then add products to it.
*
* @return a product catalog
*/
private Catalog loadCatalog() {

Catalog catalog = new Catalog();

catalog.addProduct(
new Coffee("C001", "Colombia, Whole, 1 lb", 17.99,
"Colombia", "Medium", "Rich and Hearty", "Rich",
"Medium", "Full"));
catalog.addProduct(
new Coffee("C002", "Colombia, Ground, 1 lb", 18.75,
"Colombia", "Medium", "Rich and Hearty", "Rich",
"Medium","Full"));
catalog.addProduct(
new Coffee("C003", "Italian Roasts, Whole, 1 lb",
16.80, "Latin American Blend", "Italian Roast",
"Dark and heavy", "Intense", "Low", "Medium"));
catalog.addProduct(
new Coffee("C004", "Italian Roasts, Ground, 1 lb",
17.55, "Latin American Blend", "Italian Roast",
"Dark and heavy", "Intense", "Low", "Medium"));
catalog.addProduct(
new Coffee("C005", "French Roasts, Whole, 1 lb",
16.80, "Latin American Blend", "French Roast",
"Bittersweet, full intense", "Intense, full", "None", "Medium"));
catalog.addProduct(
new Coffee("C006", "French Roasts, Ground, 1 lb",
17.55, "Latin American Blend", "French Roast",
"Bittersweet, full intense", "Intense, full", "None", "Medium"));
catalog.addProduct(
new Coffee("C007", "Guatemala, Ground, 1 lb", 17.99,
"Guatemala", "Medium", "Rich and complex", "Spicy",
"Medium to high", "Medium to full"));
catalog.addProduct(
new Coffee("C008", "Guatemala, Ground, 1 lb", 18.75,
"Guatemala", "Medium", "Rich and complex", "Spicy",
"Medium to high", "Medium to full"));
catalog.addProduct(
new Coffee("C009", "Guatemala, Whole, 1 lb", 19.99,
"Sumatra", "Medium", "Vibrant and powdery",
"Like dark chocolate", "Gentle", "Rich and full"));
catalog.addProduct(
new Coffee("C010", "Guatemala, Ground, 1 lb", 20.50,
"Sumatra", "Medium", "Vibrant and powdery",
"Like dark chocolate", "Gentle", "Rich and full"));
catalog.addProduct(
new Coffee("C011", "Special Blend, Whole, 1 lb",
16.80, "Latin American Blend", "Dark roast",
"Full, roasted flavor", "Hearty", "Bold and rich", "Full"));
catalog.addProduct(
new Coffee("C012", "Special Blend, Ground, 1 lb",
17.55, "Latin American Blend", "Dark roast",
"Full, roasted flavor", "Hearty", "Bold and rich", "Full"));

catalog.addProduct(
new CoffeeBrewer("B001", "Home Coffee Brewer",
150.00, "Brewer 100", "Pourover", 6));
catalog.addProduct(
new CoffeeBrewer("B002", "Coffee Brewer, 2 Warmers",
200.00, "Brewer 200", "Pourover", 12));
catalog.addProduct(
new CoffeeBrewer("B003", "Coffee Brewer, 3 Warmers",
280.00, "Brewer 210", "Pourover", 12));
catalog.addProduct(
new CoffeeBrewer("B004", "Commercial Brewer, 20 cups",
380.00, "Quick Coffee 100", "Automatic", 20));
catalog.addProduct(
new CoffeeBrewer("B005", "Commercial Brewer, 40 cups",
480.00, "Quick Coffee 200", "Automatic", 40));

catalog.addProduct(
new Product("A001", "Almond Flavored Syrup", 9.00));
catalog.addProduct(
new Product("A002", "Irish Creme Flavored Syrup", 9.00));
catalog.addProduct(
new Product("A003", "Mint Flavored syrup", 9.00));
catalog.addProduct(
new Product("A004", "Caramel Flavored Syrup", 9.00));
catalog.addProduct(
new Product("A005", "Gourmet Coffee Cookies", 12.00));
catalog.addProduct(
new Product("A006", "Gourmet Coffee Travel Thermo", 18.00));
catalog.addProduct(
new Product("A007", "Gourmet Coffee Ceramic Mug", 8.00));
catalog.addProduct(
new Product("A008", "Gourmet Coffee 12 Filters", 15.00));
catalog.addProduct(
new Product("A009", "Gourmet Coffee 36 Filters", 45.00));

return catalog;
}

/**
* Initializes the sales object.
*/
private void loadSales(Catalog catalog) {

Order orderOne = new Order();

orderOne.addItem(new OrderItem(catalog.getProduct("C001"), 5));
this.sales.addOrder(orderOne);

Order orderTwo = new Order();

orderTwo.addItem(new OrderItem(catalog.getProduct("C002"), 2));
orderTwo.addItem(new OrderItem(catalog.getProduct("A001"), 2));
this.sales.addOrder(orderTwo);

Order orderThree = new Order();

orderThree.addItem(new OrderItem(catalog.getProduct("B002"), 1));
this.sales.addOrder(orderThree);
}

/**
* Displays a menu of options and verifies the user's choice.
*
* @return an integer in the range [0,3]
*/
private int getChoice() throws IOException {

int input;

do {
try {
stdErr.println();
stdErr.print("[0] Quit\n"
+ "[1] Display sales (Plain Text)\n"
+ "[2] Display sales (HTML)\n"
+ "[3] Display sales (XML)\n"
+ "choice> ");
stdErr.flush();

input = Integer.parseInt(stdIn.readLine());

stdErr.println();

if (0 <= input && 3 >= input) {
break;
} else {
stdErr.println("Invalid choice: " + input);
}
} catch (NumberFormatException nfe) {
stdErr.println(nfe);
}
} while (true);

return input;
}

/**
* Changes the sales formatter.
*
* @param newFormatter a sales formatter
*/
private void setSalesFormatter(SalesFormatter newFormatter){
this.salesFormatter = newFormatter;
}

/**
* Displays the sales information in the current format.
*/
private void displaySales() {
System.out.println(this.salesFormatter.formatSales(sales));
}

/**
* Presents the user with a menu of options and executes the
* selected task.
*/
private void run() throws IOException {

int choice = getChoice();

while (choice != 0) {

if (choice == 1) {

this.setSalesFormatter(PlainTextSalesFormatter.getSingletonInstance());
this.displaySales();

} else if (choice == 2) {

this.setSalesFormatter(HTMLSalesFormatter.getSingletonInstance());
this.displaySales();

} else if (choice == 3) {

this.setSalesFormatter(XMLSalesFormatter.getSingletonInstance());
this.displaySales();
}

choice = getChoice();
}
}
}

注意事项

接口的继承及重写

在GourmetCoffee类中通过setSalesFormatter()改写本类中的salesFormatter,通过formatSales实现多态