学习总结

前言:

知识点:在最近12到15周的学习里,笔者主要学习了JavaFX的相关知识,熟悉了JavaFx的基础知识的使用。同时,还了解了Java面向对象程序设计中的各种设计模式的基本套路以及使用。对于Java中的各种包和方法都有了一点熟悉。

题量:这几周总共进行了三次PTA作业,题量中等。

难度:难度适中,主要考察同学们的设计思维以及对输入格式的检验。

PTA:

电信计费系列1-座机计费:

  实现一个简单的电信计费程序,能够根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。每条通讯信息单独计费后累加,不是将所有时间累计后统一计费。格式:号码+英文空格符+总的话费+英文空格符+余额每个用户一行,用户之间按号码字符从小到大排序。输入包括开户信息以及通讯信息。

设计与分析本题给出类图,我按照类图实现了部分程序代码。首先将UserRecords类的代码完善,同时在UserRecord类中建立列表,用于存储通话记录信息,为了实现计费类,我还编写了LandPhoneCharging类。UserRecords类作为计费类中的calCost方法的参数,两者应为组合关系。之后,我按照类图实现了计费规则类以及通讯记录类的代码。在通讯记录类中为了规范日期时间格式,使用到了Java包中的SimpleDateFormat类。其中计费规则类是计费类的属性,用于计算不同类型的通话记录。通讯记录则属于UserRecord类的属性列表中的元素,这些操作都是为了符合面向对象程序设计原则中的单一职责原则。同时在Main方法编写接受输入的循环方法,到输入字符串与"end"对等时即结束循环。同时我在Main类中实现了static类型的部分方法例如calDiffFromDate方法,是为了计算通讯记录的通话时长。在计费规则中直接调用Main.该方法即可,提高代码复用性。并实现isUser方法,判断开户的输入是已经开户。为了实现用户按照号码字符从大到小排序输出,则重写了Collection类中的CompareTo方法。

反思总结:本题作为电信计费类的第一部曲,比较简单实现。因为本题只计算座机类的计费,所以我为了简便代码,很多抽象类都没有实现,例如ChargeMode作为抽象计费类,我直接实现了本应作为它的子类的LandPhoneCharging类。以及作为父类的CommunicationRecord类也没有实现,而是跳过它实现它的子类。这为我之后实现移动电话和座机复杂计费程序增加了一定工作量,也导致代码的可扩展性不高。同时,我在Main里面实现接受输入的方法,也不符合面向对象程序设计的单一职责原则。

改进建议:写代码切记偷懒,可以通过实现算法的优化来达到工作量的减少,但不能以牺牲代码的健壮性和可扩展性为代价。同时,建议增加一个业务类,来接受输入以及对输入数据的处理,符合面向对象程序设计原则中的单一职责原则以及迪米特法则。对于检查是否为已经开户的号码,可以直接待用ArrayList的contain方法即可实习功能,不必再写方法进行遍历。

类图如下:

 

 

 

 

 

 

 关键代码:

 

while (!string.equals("end")) {
String str[] = string.split(" ");
if (!string.matches(patten2) && !string.matches(patten1)) {

} else if (str[0].substring(0,6).equals("u-0791")) {
String number = str[0].substring(2);
if (isUser(number,users)) {

}else if (number.matches("[0][7][9][1][0-9]{7}")||number.matches("[0][7][9][1][0-9]{8}")) {
User user = new User(number);
users.add(user);
}
}else if (string.matches(patten1)) {
Date startTime = new Date();
Date endTime = new Date();
String callNum = str[0].substring(2);
String answerNum = str[1];
SimpleDateFormat content = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
startTime = content.parse(str[2] + " " + str[3]);
endTime = content.parse(str[4] + " "+ str[5]);
if (isUser(callNum,users)) {
int n = findUserNum(callNum,users);
CallRecord callRecord = new CallRecord(startTime,endTime,callNum,answerNum);
int check = checkAnswer(answerNum);
if (check == 1) {
users.get(n).getUserRecords().addAnswerCityRecords(callRecord);
}else if (check == 2){
users.get(n).getUserRecords().addAnswerProvinceRecords(callRecord);
}else if (check == 3) {
users.get(n).getUserRecords().addAnswerLandRecords(callRecord);
}
}
}
string = input.nextLine();
}
Collections.sort(users, new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getNumber().compareTo(o2.getNumber());
}
});
for (int i = 0;i < users.size();i++) {
System.out.println(String.format("%s %.1f %.1f",users.get(i).getNumber(),users.get(i).calCost(),
users.get(i).calBalance()));
}
}

 

电信计费系列2-手机+座机计费:

  实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别为针对市内座机用户采用的计费方式(与电信计费系列1内容相同),以及2、针对手机用户采用实时计费方式;其中的计费方式,这里就不再赘述。但有需要说明的是,被叫电话属于市内、省内还是国内由被叫电话的接听地点区号决定,比如以下案例中,南昌市手机用户13307912264在区号为020的广州接听了电话,主叫号码应被计算为拨打了一个省外长途,同时,手机用户13307912264也要被计算省外接听漫游费。

设计与分析:本题是对上一题的扩充的,增加了手机用户的计费模式,所以我实现了本没有实现的抽象类,同时调用了增加了ChargeMode的子类MobilePhoneCharging类,用于实现手机用户的计费,并且在UserRecord中增加了callingProvinceRoamRecord(省内漫游拨打)、callingLandRoamRecord(省外漫游拨打)、answerLandRoamRecord(省外漫游接听)的用于存放手机用户漫游接听拨打的通话记录的ArrayList列表。同时也增加了ChargeRule的子类MobilePhoneInCityRule等用于实现手机计费的计费规则类。同时编写了业务类,并在业务类中实现接受输入以及判断的方法。

反思总结:作为第二个电信计费类题目,在原题的基础上增加了手机用户计费,如果原代码的可扩展性较好,要实现并不困难,重难点在于判断输入类型是否开户,以及将各种通话记录精准的存入相应的通话记录数组即可。正则表达式也是很关键的一个点,用于检验是否为正确输入,否则不进行操作。

类图如下:

关键代码:

正则表达式部分:

 

String datePatten = "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.(((0?[13578]|1[02])\\.(" +
"[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" +
"[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" + 
"\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])"; //日期格式检验
String patten1 = "[u][-][0][7][9][1][0-9]{7,8}\\s[0]";
String patten2 = "[u][-][1][3][0-9]{9}\\s[1]";

 

String patten3 = "[t]-0791[0-9]{7,8}\\s" + "0[0-9]{9,11}\\s"+datePatten + "\\s" + datePatten;//座机打座机
String patten4 = "[t]-0791[0-9]{7,8}\\s" +"1[0-9]{10}\\s"+"0[0-9]{2,3}\\s"+datePatten + "\\s" + datePatten;//座机打手机
String patten5 = "[t]-1[0-9]{10}\\s" +"0[0-9]{2,3}\\s"+"0[0-9]{10,11}\\s"+datePatten + "\\s" + datePatten;//手机打座机
String patten6 = "[t]-1[0-9]{10}\\s" +"0[0-9]{2,3}\\s"+"1[0-9]{10}\\s"+"0[0-9]{2,3}\\s"+datePatten + "\\s" + datePatten;//手机打手机

排序部分:

Collections.sort(users, new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getNumber().compareTo(o2.getNumber());
}
});

电信计费系列3-短信计费

实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
1、接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
2、如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。

设计与分析:本题作为本学期最后一次的电信计费系列题目,只需要实现短信计费即可,相比于前两次的电信计费题目都更简单一些。所以我在原本代码的基础做了删减,同时增加了一些跟需求有关的类,例如短信计费规则类MassageRule,短信的计费类则直接使用原本代码的MobilePhoneChargeing即可,因为本题针对手机用户收发短信进行计费。

反思总结:

改进建议:

未写完,太困了,等我睡醒写,球球。。。。

posted @ 2022-06-15 23:00  21201618-吕晨哲  阅读(110)  评论(0)    收藏  举报