目录
前言
总结之前所涉及到的知识点、题量、难度等情况
- 虽然这个学期过去大半,但是说实话对Java还是没有什么掌握,全靠eclipse报错修改代码拯救。到现在,菜单计价程序也写到了5,接触的知识点也挺多的。像抽象类和接口,类间关系(关联、依赖、组合、聚集、继承)还有一些导入的包中的方法什么的。
- 最近的两次菜单,第四次对比之前主要增加了异常情况的分析和一些相关输出,第五次呢,则是和第四次差不多,在第三次菜单的基础上修改,增加了特色菜和菜系、口味的概念,还要求了一些相关的输出。老实说,我觉得菜单系列的题目难度和题量一直挺大的。期中考试的难度和题量是可以接受的,但是还是没有满分吧,因为对Comparable接口还不太熟悉,之前的使用都是对着csdn一点点敲出来的,所以没能在规定的时间内做出来吧。
设计与分析
1.菜单计价程序-4
- 完成情况
以下是截取了部分题目------
本次课题比菜单计价系列-3增加的异常情况:
1、菜谱信息与订单信息混合,应忽略夹在订单信息中的菜谱信息。输出:"invalid dish"
2、桌号所带时间格式合法(格式见输入格式部分说明,其中年必须是4位数字,月、日、时、分、秒可以是1位或2位数),数据非法,比如:2023/15/16 ,输出桌号+" date error"
3、同一桌菜名、份额相同的点菜记录要合并成一条进行计算,否则可能会出现四舍五入的误差。
4、重复删除,重复的删除记录输出"deduplication :"+序号。
5、代点菜时,桌号不存在,输出"Table number :"+被点菜桌号+" does not exist";本次作业不考虑两桌记录时间不匹配的情况。
6、菜谱信息中出现重复的菜品名,以最后一条记录为准。
7、如果有重复的桌号信息,如果两条信息的时间不在同一时间段,(时段的认定:周一到周五的中午或晚上是同一时段,或者周末时间间隔1小时(不含一小时整,精确到秒)以内算统一时段),此时输出结果按不同的记录分别计价。
8、重复的桌号信息如果两条信息的时间在同一时间段,此时输出结果时合并点菜记录统一计价。前提:两个的桌号信息的时间都在有效时间段以内。计算每一桌总价要先合并符合本条件的饭桌的点菜记录,统一计价输出。
9、份额超出范围(1、2、3)输出:序号+" portion out of range "+份额,份额不能超过1位,否则为非法格式,参照第13条输出。
10、份数超出范围,每桌不超过15份,超出范围输出:序号+" num out of range "+份数。份数必须为数值,最高位不能为0,否则按非法格式参照第16条输出。
11、桌号超出范围[1,55]。输出:桌号 +" table num out of range",桌号必须为1位或多位数值,最高位不能为0,否则按非法格式参照第16条输出。
12、菜谱信息中菜价超出范围(区间(0,300)),输出:菜品名+" price out of range "+价格,菜价必须为数值,最高位不能为0,否则按非法格式参照第16条输出。
13、时间输入有效但超出范围[2022.1.1-2023.12.31],输出:"not a valid time period"
14、一条点菜记录中若格式正确,但数据出现问题,如:菜名不存在、份额超出范围、份数超出范围,按记录中从左到右的次序优先级由高到低,输出时只提示优先级最高的那个错误。
15、每桌的点菜记录的序号必须按从小到大的顺序排列(可以不连续,也可以不从1开始),未按序排列序号的输出:"record serial number sequence error"。当前记录忽略。(代点菜信息的序号除外)
16、所有记录其它非法格式输入,统一输出"wrong format"
17、如果记录以“table”开头,对应记录的格式或者数据不符合桌号的要求,那一桌下面定义的所有信息无论正确或错误均忽略,不做处理。如果记录不是以“table”开头,比如“tab le 55 2023/3/2 12/00/00”,该条记录认为是错误记录,后面所有的信息并入上一桌一起计算。
本次作业比菜单计价系列-3增加的功能:
菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+基础价格+"T"
菜价的计算方法:
周一至周五 7折, 周末全价。
注意:不同的四舍五入顺序可能会造成误差
请按以下步骤累计一桌菜的菜价:计算每条记录的菜价:将每份菜的单价按份额进行四舍五入运算后,乘以份数计算多份的价格,然后乘以折扣,再进行四舍五入,得到本条记录的最终支付价格,最后将所有记录的菜价累加得到整桌菜的价格。
import java.util.Scanner;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParseException;
public class Main {
public static void main(String[] args) {
Main main = new Main();
Scanner scanner = new Scanner(System.in);
ArrayList<String> messageList = new ArrayList<String>();
ArrayList<String> arrayList = new ArrayList<String>();
ArrayList<Table> tArrayList = new ArrayList<Main.Table>();
String string = "";
while (true) {
string = scanner.nextLine();
if ("end".equals(string)) {
break;
}
arrayList.add(string);
}
Menu menu = main.new Menu();
menu.dishs = new Dish[0];
int n = 0;
for (int i = 0; i < arrayList.size(); i++) {
String[] strings = arrayList.get(i).split(" ");
if (strings.length==0) {
messageList.add("wrong format");
break;
}
if (strings.length > 3&&strings[0].charAt(0)=='t') {
n = i;
break;
}else if(strings.length > 3){
messageList.add("wrong format");
continue;
}
String dName = strings[0];
String dPrice = strings[1];
if (dPrice.charAt(0) == '0') {
messageList.add("wrong format");
continue;
}
int hp = 0;
try {
hp = Integer.parseInt(dPrice);
} catch (Exception e) {
messageList.add("wrong format");
continue;
}
if (hp >= 300 || hp <= 0) {
messageList.add(dName + " price out of range "+hp);
continue;
}
if (menu.searthDish(dName) != null) {
for (int j = 0; j < menu.dishs.length; j++) {
if (menu.dishs[j].equals(dName)) {
menu.dishs[j].unit_price = hp;
}
}
} else {
Dish dish = main.new Dish();
if (strings.length == 2) {
dish.name = dName;
dish.unit_price = hp;
} else if (strings.length == 3) {
dish.name = dName;
dish.unit_price = hp;
dish.isT = true;
}
menu.addDish(dish);
}
}
ArrayList<Integer> arrayLista = new ArrayList<Integer>();// 桌号开始下标
for (int i = n; i < arrayList.size(); i++) {
if (arrayList.get(i).split(" ")[0].length() > 2 && arrayList.get(i).split(" ")[0].charAt(0) == 't') {
arrayLista.add(i);
}
}
for (int i = 0; i < arrayLista.size(); i++) {
Table table = main.new Table();
Order order = main.new Order();
order.records = new Record[0];
table.order = order;
int t1 = arrayLista.get(i);
String[] strings = arrayList.get(t1).split(" ");
if (strings.length==0) {
messageList.add("wrong format");
continue;
}
if (strings[0].equals("table")) {
if (strings[1].charAt(0) == '0') {
messageList.add("wrong format");
continue;
}
int tNum = 0;
try {
tNum = Integer.parseInt(strings[1]);
} catch (Exception e) {
messageList.add("wrong format");
continue;
}
if (tNum > 55 && tNum <= 0) {
messageList.add(tNum + " num out of range");
continue;
}
if (strings[2].split("/")[0].length() != 4) {// year
messageList.add("wrong format");
continue;
}
if (strings[2].split("/")[1].length() > 2 || strings[2].split("/")[1].length() < 1) {// month
messageList.add("wrong format");
continue;
}
if (strings[2].split("/")[2].length() > 2 || strings[2].split("/")[2].length() < 1) {// day
messageList.add("wrong format");
continue;
}
if (strings[3].split("/")[0].length() > 2 || strings[3].split("/")[0].length() < 1) {// hour
messageList.add("wrong format");
continue;
}
if (strings[3].split("/")[1].length() > 2 || strings[3].split("/")[1].length() < 1) {// minute
messageList.add("wrong format");
continue;
}
if (strings[3].split("/")[2].length() > 2 || strings[3].split("/")[2].length() < 1) {// moment
messageList.add("wrong format");
continue;
}
DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss");
sdf.setLenient(false);
Date date = null;
try {
date = sdf.parse(strings[2] + " " + strings[3]);
} catch (ParseException e) {
messageList.add(tNum + " date error");
continue;
}
table.date = date;
table.tableNum = tNum;
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd");
SimpleDateFormat sdf2 = new SimpleDateFormat("HH/mm/ss");
Date date1 = null;
Date date2 = null;
try {
date1 = sdf1.parse("2022/1/1");
date2 = sdf1.parse("2023/12/31");
if (date1.compareTo(sdf1.parse(strings[2])) > 0 || date2.compareTo(sdf1.parse(strings[2])) < 0) {
messageList.add("not a valid time period");
continue;
}
} catch (ParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int dayNum = calendar.get(Calendar.DAY_OF_WEEK) - 1;
Date bdate = null;
Date edate = null;
Date bdate1 = null;
Date edate1 = null;
Date bdate2 = null;
Date edate2 = null;
Date nowDate = null;
try {
bdate = sdf2.parse("9/29/59");
edate = sdf2.parse("21/30/00");
bdate1 = sdf2.parse("10/30/00");
edate1 = sdf2.parse("14/30/00");
bdate2 = sdf2.parse("16/59/59");
edate2 = sdf2.parse("20/30/00");
nowDate = sdf2.parse(strings[3]);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (dayNum == 6 || dayNum == 0) {// 周末
if (timeCalendar(nowDate, bdate, edate)) {// 全价
table.dicount = 1.0;
} else {
messageList.add("table " + tNum + " out of opening hours");
continue;
}
} else {// 工作日
if (timeCalendar(nowDate, bdate1, edate1)) {// 6折
table.dicount = 0.6;
} else if (timeCalendar(nowDate, bdate2, edate2)) {// 8折
table.dicount = 0.8;
} else {
messageList.add("table " + tNum + " out of opening hours");
continue;
}
}
messageList.add("table"+" "+tNum + ": ");
if (t1 == arrayList.size()-1) {
} else {
int fNum;
if (arrayLista.get(arrayLista.size()-1) == t1) {
fNum = arrayList.size();
} else {
fNum = arrayLista.get(i + 1);
}
ArrayList<Integer> delNumArrayList = new ArrayList<Integer>();
int numb = 0;
for (int j = t1 + 1; j < fNum; j++) {// 点菜记录
String[] strings2 = arrayList.get(j).split(" ");
if (strings2.length==0) {
messageList.add("wrong format");
continue;
}
int Num1;
try {
Num1 = Integer.parseInt(strings2[0]);
} catch (Exception e) {
messageList.add("invalid dish");
continue;
}
if (strings2[0].charAt(0)=='0') {
messageList.add("wrong format");
continue;
}
if (strings2.length == 5) {// 代点菜
boolean flag = false;
if (tArrayList.get(0).tableNum == Num1)
flag = true;
if (flag) {
messageList.add("Table number :" + Num1 + " does not exist");
continue;
}
if (strings2[3].length() > 1) {
messageList.add("wrong format");
continue;
} else {
String dishName = strings2[2];// 菜名
int dishP;
int dishN;
if (strings2[4].charAt(0) == '0') {
messageList.add("wrong format");
continue;
}
try {
dishP = Integer.parseInt(strings2[3]);
dishN = Integer.parseInt(strings2[4]);
} catch (Exception e) {
messageList.add("wrong format");
continue;
}
if (menu.searthDish(dishName) == null) {
messageList.add(dishName + " does not exist");
continue;
}
Dish dish = menu.searthDish(dishName);
if (dish.isT) {
if (dishP != 1 && dishP != 3&& dishP != 2) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
} else {
if (dishP != 1 && dishP != 3 && dishP != 2) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
}
if (dishN > 15 || dishN < 1) {
messageList.add(Num1 + " num out of range " + dishN);
continue;
}
boolean f1 = true;
if (f1) {
table.order.addARecord(Num1, dish, dishP, dishN);
}
}
} else if (strings2.length == 2) {
if (!strings2[1].equals("delete")) {
messageList.add("wrong format");
continue;
} else {
boolean flag = false;
for (Integer n2 : delNumArrayList) {
if (n2 == Num1) {
flag = true;
}
}
if (flag) {
messageList.add("deduplication " + Num1);
continue;
}
if (table.order.findRecordByNum(Num1) == -1) {
messageList.add("delete error");
continue;
}
table.order.delARecordByOrderNum(Num1);
delNumArrayList.add(Num1);
}
} else if (strings2.length == 4) {
if (strings2[2].length() > 1) {
messageList.add("wrong format");
continue;
} else {
String dishName = strings2[1];// 菜名
int dishP;
int dishN;
if (strings2[3].charAt(0) == '0') {
messageList.add("wrong format");
continue;
}
try {
dishP = Integer.parseInt(strings2[2]);
dishN = Integer.parseInt(strings2[3]);
} catch (Exception e) {
messageList.add("wrong format");
continue;
}
if (Num1 <= numb) {
messageList.add("record serial number sequence error");
continue;
}
if (menu.searthDish(dishName) == null) {
messageList.add(dishName + " does not exist");
continue;
}
Dish dish = menu.searthDish(dishName);
if (dish.isT) {
if (dishP != 1 && dishP != 3&& dishP != 2) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
} else {
if (dishP != 1 && dishP != 3 && dishP != 2) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
}
if (dishN > 15 || dishN < 1) {
messageList.add(Num1 + " num out of range " + dishN);
continue;
}
numb = Num1;
boolean f1 = true;
for (int k = 0; k < table.order.records.length; k++) {
if (table.order.records[k].d.name.equals(dishName)
&& table.order.records[k].portion == dishP) {
table.order.records[k].num = table.order.records[k].num + dishN;
f1 = false;
}
}
if (f1) {
table.order.addARecord(Num1, dish, dishP, dishN);
messageList.add(Num1 + " " + dishName + " " + dish.getPrice(dishP) * dishN);
}
}
} else {
messageList.add("wrong format");
continue;
}
}
}
} else {
messageList.add("wrong format");
if (t1 == arrayList.size()-1) {
} else {
int fNum;
if (arrayLista.get(arrayLista.size() - 1) == t1) {
fNum = arrayList.size();
} else {
fNum = arrayLista.get(i + 1)+1;
}
Table table2 = tArrayList.get(tArrayList.size()-1);
ArrayList<Integer> delNumArrayList = new ArrayList<Integer>();
int numb = table2.order.records[table2.order.records.length-1].orderNum;
for (int j = t1 + 1; j < fNum; j++) {// 点菜记录
String[] strings2 = arrayList.get(j).split(" ");
if (strings2.length==0) {
messageList.add("wrong format");
continue;
}
int Num1;
try {
Num1 = Integer.parseInt(strings2[0]);
} catch (Exception e) {
messageList.add("invalid dish");
continue;
}
if (strings2[0].charAt(0)=='0') {
messageList.add("wrong format");
continue;
}
if (strings2.length == 5) {// 代点菜
boolean flag = true;
for (int k = 0; k < tArrayList.size(); k++) {
if (tArrayList.get(k).tableNum == Num1) {
flag = false;
}
}
if (flag) {
messageList.add("Table number :" + Num1 + " does not exist");
continue;
}
if (strings2[3].length() > 1) {
messageList.add("wrong format");
continue;
} else {
String dishName = strings2[2];// 菜名
int dishP;
int dishN;
if (strings2[4].charAt(0) == '0') {
messageList.add("wrong format");
continue;
}
try {
dishP = Integer.parseInt(strings2[3]);
dishN = Integer.parseInt(strings2[4]);
} catch (Exception e) {
messageList.add("wrong format");
continue;
}
if (menu.searthDish(dishName) == null) {
messageList.add(dishName + " does not exist");
continue;
}
Dish dish = menu.searthDish(dishName);
if (dish.isT) {
if (dishP != 1 && dishP != 3) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
} else {
if (dishP != 1 && dishP != 3 && dishP != 2) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
}
if (dishN > 15 || dishN < 1) {
messageList.add(Num1 + " num out of range " + dishN);
continue;
}
boolean f1 = true;
if (f1) {
table2.order.addARecord(Num1, dish, dishP, dishN);
}
}
} else if (strings2.length == 2) {
if (!strings2[1].equals("delete")) {
messageList.add("wrong format");
continue;
} else {
boolean flag = false;
for (Integer n2 : delNumArrayList) {
if (n2 == Num1) {
flag = true;
}
}
if (flag) {
messageList.add("deduplication " + Num1);
continue;
}
if (table2.order.findRecordByNum(Num1) == -1) {
messageList.add("delete error");
continue;
}
table2.order.delARecordByOrderNum(Num1);
delNumArrayList.add(Num1);
}
} else if (strings2.length == 4) {
if (strings2[2].length() > 1) {
messageList.add("wrong format");
continue;
} else {
String dishName = strings2[1];// 菜名
int dishP;
int dishN;
if (strings2[3].charAt(0) == '0') {
messageList.add("wrong format");
continue;
}
try {
dishP = Integer.parseInt(strings2[2]);
dishN = Integer.parseInt(strings2[3]);
} catch (Exception e) {
messageList.add("wrong format");
continue;
}
if (Num1 <= numb) {
messageList.add("record serial number sequence error");
continue;
}
if (menu.searthDish(dishName) == null) {
messageList.add(dishName + " does not exist");
continue;
}
Dish dish = menu.searthDish(dishName);
if (dish.isT) {
if (dishP != 1 && dishP != 3) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
} else {
if (dishP != 1 && dishP != 3 && dishP != 2) {
messageList.add(Num1 + " portion out of range " + dishP);
continue;
}
}
if (dishN > 15 || dishN < 1) {
messageList.add(Num1 + " num out of range " + dishN);
continue;
}
numb = Num1;
boolean f1 = true;
for (int k = 0; k < table2.order.records.length; k++) {
if (table2.order.records[k].d.name.equals(dishName)
&& table2.order.records[k].portion == dishP) {
table2.order.records[k].num = table2.order.records[k].num + dishN;
f1 = false;
}
}
if (f1) {
table2.order.addARecord(Num1, dish, dishP, dishN);
messageList.add(Num1 + " " dishNam+" " + dish.getPrice(dishP) *dishN);
}
}
} else {
messageList.add("wrong format");
continue;
}
}
}
}
if (table.tableNum!=0) {
tArrayList.add(table);
}
}
for (int j = 0; j < messageList.size(); j++) {
System.out.println(messageList.get(j));
}
for (int j = 0; j < tArrayList.size()-1; j++) {
if (tArrayList.get(0).tableNum<tArrayList.get(1).tableNum) {
Table table = main.new Table();
table = tArrayList.get(1);
tArrayList.set(1, tArrayList.get(0));
tArrayList.set(0, table);
}
}
for (int j = 0; j < tArrayList.size(); j++) {
int tableNum = tArrayList.get(j).tableNum;
Order order =tArrayList.get(j).order;
int sum = 0;
int sumP = 0;
for (int i = 0; i < order.records.length; i++) {
Record record = order.records[i];
if (record.d.isT&&tArrayList.get(j).dicount!=1.0) {
sum +=(int)Math.round(record.getPrice());
sumP +=(int)Math.round(record.getPrice()*0.7);
}else {
sum +=record.getPrice();
sumP +=(int)Math.round(record.getPrice()*tArrayList.get(j).dicount);
}
}
if (j==tArrayList.size()-1) {
System.out.print("table"+" "+tableNum+":"+" "+sum+" "+sumP);
}else {
System.out.println("table"+" "+tableNum+":"+" "+sum+" "+sumP);
}
}
}
// 菜品类
class Dish {
String name;// 菜品名称
int unit_price; // 单价
boolean isT = false;
int getPrice(int portion) {// 计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
double money = 0;
switch (portion) {
case 1:// 小份
money = this.unit_price * 1.0;
break;
case 2:// 中份
money = 1.5 * this.unit_price;
break;
case 3:// 大份
money = this.unit_price * 2.0;
break;
}
return (int) Math.round(money);
}
}
// 菜谱类:对应菜谱,包含饭店提供的所有菜的信息
class Menu {
Dish[] dishs;// 菜品数组,保存所有菜品信息
Dish searthDish(String dishName) {
for (int i = 0; i < dishs.length; i++) {
if (dishs[i].name.equals(dishName)) {
return dishs[i];
}
}
return null;
}
Dish addDish(Dish dish) {// 添加一道菜品信息
Dish[] dishs1 = new Dish[dishs.length + 1];
for (int i = 0; i < dishs.length; i++) {
dishs1[i] = dishs[i];
}
dishs1[dishs.length] = dish;
dishs = dishs1;
return dish;
}
}
// 点菜记录类:保存订单上的一道菜品记录
class Record {
int orderNum;// 序号
Dish d;// 菜品
int portion;// 份额(1/2/3代表小/中/大份)
int num;// 份数
int getPrice() {// 计价,计算本条记录的价格
return (int) Math.round(this.d.getPrice(this.portion) * num);
}
}
// 订单类:保存用户点的所有菜的信息
class Order {
Record[] records;// 保存订单上每一道的记录
int getTotalPrice() {// 计算订单的总价
int sum = 0;
for (int i = 0; i < records.length; i++) {
sum += records[i].getPrice();
}
return sum;
}
// 添加一条菜品信息到订单中
Record addARecord(int orderNum, Dish dish, int portion, int num) {
Record record = new Record();
record.orderNum = orderNum;
record.d = dish;
record.portion = portion;
record.num = num;
Record[] records1 = new Record[this.records.length + 1];
for (int i = 0; i < this.records.length; i++) {
records1[i] = this.records[i];
}
records1[this.records.length] = record;
this.records = records1;
return record;
}
// 根据序号删除一条记录
void delARecordByOrderNum(int orderNum) {
int n = this.findRecordByNum(orderNum);
Record[] records1 = new Record[this.records.length - 1];
for (int i = 0; i < this.records.length; i++) {
if (i == n) {
continue;
}
if (i > n) {
records1[i] = this.records[i - 1];
} else {
records1[i] = this.records[i];
}
}
this.records = records1;
}
// 根据序号查找一条记录
int findRecordByNum(int orderNum) {
int n = -1;
for (int i = 0; i < this.records.length; i++) {
if (this.records[i].orderNum == orderNum) {
n = i;
}
}
return n;
}
}
class Table {
int tableNum;
Order order;
Date date;
double dicount = 0;
}
public static boolean timeCalendar(Date nowTime, Date beginTime, Date endTime) {
Calendar date = Calendar.getInstance();// 设置当前时间
date.setTime(nowTime);
Calendar begin = Calendar.getInstance();// 设置开始时间
begin.setTime(beginTime);// 开始时间
Calendar end = Calendar.getInstance();// 设置结束时间
end.setTime(endTime);// 上午结束时间
if ((date.after(begin) && date.before(end))) {// 判断是否处于开始时间之后和结束时间之前
return true;
} else {
return false;
}
}
}
运行结果如下:
⭕ 出现的问题比较多而且比较杂,尤其是和桌号有关的测试点,有几个都没过。反复检查发现tableNum有关的方法有问题,但是还没有改出来。对比第三次,增加了很多的if,else,还使用了ParseException(try,catch),增加了很多Boolean类型的方法。因为菜单计价程序-3没拿分,所以菜单-4是参考了别人的3才写出来的,所以复杂度什么的就高了很多。
PowerDesigner的类图
SourceMonitor的报表内容
(绿色环形区域即被测量维度的期望值,维度上的点则是测量得到的实际值)
2.菜单计价程序-5
那个星期一直在研究class table怎么改,就没怎么针对题目进行修改,简单加了几个add和search方法和特色菜的一些定义,我是把特色菜也放在dish里面,那几个菜系继承dish,因为修改不完全也没得分,这里就不放代码了。
3.期中考试
期中考试的前两道题目就不分析了,就是两个类的设计,基本上写到一起就是第三题,第四题差不多就是在第三题的基础上增加一个接口,就直接写第四题的代码和分析吧。
- 完成情况
在测验3的题目基础上,重构类设计,实现列表内图形的排序功能(按照图形的面积进行排序)
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
ArrayList<Shape> list = new ArrayList<>();
int choice = input.nextInt();
while(choice != 0) {
switch(choice) {
case 1://Circle
double radius = input.nextDouble();
if(radius>0)
{
Shape circle = new Circle(radius);
list.add(circle);
}
else System.out.println("Wrong Format");
break;
case 2://Rectangle
double x1 = input.nextDouble();
double y1 = input.nextDouble();
double x2 = input.nextDouble();
double y2 = input.nextDouble();
Point leftTopPoint = new Point(x1,y1);
Point lowerRightPoint = new Point(x2,y2);
Rectangle rectangle = new Rectangle(leftTopPoint,lowerRightPoint);
list.add(rectangle);
break;
}
choice = input.nextInt();
}
list.sort(Comparator.naturalOrder());//正向排序
for(int i = 0; i < list.size(); i++) {
System.out.print(String.format("%.2f", list.get(i).getArea()) + " ");
}
}
}
abstract class Shape implements Comparable<Shape> {
public Shape() {}
public abstract double getArea();
@Override
public int compareTo(Shape other) {
if (this.getArea() < other.getArea()) {
return -1;
} else if (this.getArea() > other.getArea()) {
return 1;
} else {
return 0;
}
}
}
class Circle extends Shape {
private double radius = 0;
public Circle() {}
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}
class Rectangle extends Shape {
private Point topLeftPoint;
private Point lowerRightPoint;
public Rectangle() {
topLeftPoint = new Point();
lowerRightPoint = new Point();
}
public Rectangle(Point topLeftPoint, Point lowerRightPoint) {
this.topLeftPoint = topLeftPoint;
this.lowerRightPoint = lowerRightPoint;
}
public Point getTopLeftPoint() {
return topLeftPoint;
}
public void setTopLeftPoint(Point topLeftPoint) {
this.topLeftPoint = topLeftPoint;
}
public Point getLowerRightPoint() {
return lowerRightPoint;
}
public void setLowerRightPoint(Point lowerRightPoint) {
this.lowerRightPoint = lowerRightPoint;
}
public double getLength() {
return Math.abs(lowerRightPoint.getX() - topLeftPoint.getX());
}
public double getHeight() {
return Math.abs(lowerRightPoint.getY() - topLeftPoint.getY());
}
@Override
public double getArea() {
return getLength() * getHeight();
}
}
class Point {
private double x;
private double y;
public Point() {}
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
PowerDesigner的类图
SourceMonitor的报表内容
踩坑心得
- 用过的类和接口,要尽量做到学会,会用
期中考试最后一题没写出来,主要是Shape类要实现Comparable接口,而我没实现。考试结束后去看了一下相关教程(http://t.csdn.cn/f3vUK). - 要注意数组下标和数据的对应关系
对输入数据进行if判断时,要注意数组中下标是从零开始,不要数错,要不然会出现输入输出对不上的情况。 - 类的设计
要提前想好哪个方法应该放在哪个类里,用什么关系实现,boolean的返回值要反复斟酌,一开始true和false的出错,会大大提升后期修改的难度。
改进建议
1) 我自己菜单系列代码类的设计不是特别完善,主函数较长,应该可以设计一个判断输入数据类型的类,判断满足之后再执行对应方法。
2) 可以适当的加一些要求基础的与菜单这类长代码有一定相关性的小题目,激发学生的学习兴趣,让他们有反复学习、学懂的动力。
总结
1) 这几周的大作业和测试,让我深刻认识到了面向对象的特点以及类设计的重要性,学会了使用正则表达式、Exception以及一些接口,了解了抽象类和接口的区别。
2) 在之后的学习力,要努力掌握接口、javafx的使用和其他知识,改进类间关系,增强代码的可读性,努力减小耦合度和圈复杂度。