PTA题目杂谈
PTA题目杂谈
————第二次Blog作业
这两次的pta作业并没有出现什么和上次一样很难的题目,总而言之还是上次的题目的逻辑摸索过程太折磨人了,而这两次的pta作业虽然在编码上难度仍然不低于上次的电梯作业,但由于有充足的数据或者说明显的设计思路,所以这两次的难度真不高,以至于我好奇这个blog作业到底有什么可以讲的。尽管三道题全是迭代,奈何思路明确啊,基本都是三遍内AC。
在OOP8中,第一题有一个多态,这是多态思想第一次出现在题目中,我理解下的多态就是一个子类的项目可以通过父类进行声明然后调用子类的一些覆写父类的方法。当然子类特有的一些方法并且涉及子类特有的数据当然是无法调取的,除非一开始构造时调用的是子类的构造方法。多态的存在可以格式化父类和子类的变量的声明,以及一些特殊的用法,例如强制转化同级子类进行读取不同的方法。不过OOP8-1的难度还是约等于没有,也就多态一个用法而已。实际上你不用多态写也能AC。在回到这个雨刷问题,这个难度本身不大,也就一个组合类关系而已,几个不同的类然后让一个大Control类进行这几个类的数据交互读取而已,这个题给我最大的印象是好奇这个最终挡位是一一对应的吗, 还是可以通过一个函数算出来,当然在第二代迭代中我发现这个就是单纯一一对应。
而在OOP8的第三题,在经历过前三次的电梯的迭代后我们不得不尊重一下这位压轴的题目。结果毫不意外的 。。。。。拉了。倒不是说题有多不好吧,其实这个题的设计就完全放弃了算法上的折磨,估计老师也知道如果在算法上刁难我们估计那通过率又是个位数了。这个第三题的设计看得出来,老师想让我们好好学一下类设计。这个确实可以,你不能说这个题很难,只能说这个题目很。。。。。麻烦。没错,因为输入的量太多,并且存在多余的量(完全用不到的信息)。而且重点是遵循:单一职责原则(40%)、里氏代换原则(20%)、开闭原则(20%)、合成复用原则(20%)。
- 单一职责原则:单一职责原则指出一个类应该只有一个发生变化的原因。如果一个类承担了过多职责,当其中某项职责发生变化时,可能会导致其他职责也受到影响,增加系统出错的风险。例如,一个订单类既处理订单信息又负责订单支付逻辑,支付方式变更时,可能会误改订单信息部分。遵循此原则可使类更加专注、清晰,便于维护和扩展。此时订单类应该只负责对该订单的信息进行反馈和修改,而至于怎么支付和修改那就是Control该干的事了,而我们在刚开始讲到类的时候就讲到这个类原则。因为这是面向对象和面向过程最大的区别,而面向对象理论上也更符合编程逻辑。
- 里氏代换原则:里氏代换原则要求子类对象必须能够替换掉它们的父类对象,并且不破坏系统的正确性。这意味着子类必须完全实现父类的行为,并且可以扩展父类的行为。例如,鸟类是动物,鹦鹉是鸟类,鹦鹉可以替换鸟类出现在需要动物的地方。遵循此原则能保证继承体系的合理性,增强代码的可扩展性和可维护性。具体而言这个就是如果我们的子代必须完整的完成父类的所有“使命”,而至于有没有其他的那就看情况而定。
- 开闭原则:开闭原则强调软件实体应该对扩展开放,对修改关闭。即在不修改已有代码的基础上,通过添加新的代码来实现功能的扩展。例如,一个电商系统新增支付方式,只需添加新的支付类,无需修改原有支付代码。遵循此原则可降低系统维护成本,提高系统的灵活性和可扩展性。就这个题,我的支付方式是一个接口,而扩展新的支付方式只需要添加新的接口即可,不用再动之前的代码了。俗话说:如果代码能跑,就尽量不要动他了,本体好了就不用乱搞了。
- 合成复用原则:合成复用原则建议尽量使用组合而非继承来实现代码复用。组合是将一个类的实例作为另一个类的成员变量,通过调用成员变量的方法来实现功能。例如,汽车类包含发动机类的实例,通过调用发动机的方法来实现汽车的启动功能。遵循此原则可避免继承带来的耦合问题,增强系统的灵活性和可维护性。这个就是强调了组合和继承的不同用处,也不是说完全不让你用继承,而是说看该不该用继承,就好比你人和车不是一类,总不能人继承车去。这个时候应该组合,但同一个类下的,例如动物大类和细分的你还是要用继承。
总而言之这个题目就是让你老老实实规规矩矩的做一道类设计,并且内容不小,不过没有设计算法,基本白给。我们直接拿OOP9的迭代来讲,首先又多一个依赖倒转原则:高层模块不应依赖于低层模块,二者都应该依赖于抽象;抽象不应依赖于细节,细节应依赖于抽象。在传统的依赖关系中,高层模块(如业务逻辑层)往往直接依赖低层模块(如数据访问层)。这种依赖关系使得低层模块的变更会直接影响高层模块。依赖倒转原则则要求通过抽象(如接口或抽象类)来解耦高层和低层模块。例如,一个支付系统中,高层模块(订单处理模块)不应直接调用低层模块(支付实现模块),而是通过一个支付接口(抽象)来与低层模块交互。具体的支付方式(如支付宝、微信支付)实现该接口,高层模块只依赖于这个接口,而不关心具体的实现细节。说白了就是高层模块规范,下达指令,低级模块干活。是不是和公司一样。这个好处就是遵循依赖倒转原则可以降低模块之间的耦合度,使得系统更加灵活和可扩展。当支付方式发生变化时,只需修改具体的支付实现类,而无需修改高层模块的代码。同时,这种设计也便于单元测试和代码复用。
解释完这个原则我们再看其他的,首先就是货物和订单的类别更多了,意味着不同的订单应该有不同的计算方法,这个还好,我直接分别对货物,用户,订单,进行枚举,并且将这个枚举塞到对应的类里,修改之前的Control类即可。接下来是我的类图
![]()
总体看来耦合度还是比较低的,我具体分了四大类,存储信息的订单类,输入类,输出类,控制类。符合MVC设计架构。再具体就是
功能模块划分
- 输入模块Main类
• 使用 Scanner 从控制台读取用户输入,包括用户类型、客户信息、货物信息、航班信息、支付方式等。
• 输入数据通过多次循环确保非空,避免因用户输入空行导致程序出错。 - 数据模型
• User 类:表示用户的基本信息,包括地址、电话和姓名。
• Customer 类:继承自 User,增加了用户类型(个人或企业)和用户编号。
• Good 类:表示货物,包含货物名称、尺寸、重量、计费重量、计费费率和价格等属性。
• Flight 类:表示航班,包含航班号、起始地、目的地、日期和最大载重。
• Deal 类:表示订单,包含客户、发件人、收件人、航班、支付方式、货物列表、订单号、订单日期等信息。
• Paymethod 接口及实现类:定义了支付方式接口,具体实现包括支付宝、微信支付和现金支付。 - 业务逻辑模块
• Control 类:核心控制类,负责处理订单的重量计算、价格计算和超重检查。
o is_overweight 方法:检查货物总重量是否超过航班的最大载重,若超重则终止程序。
o count_weight 方法:计算每个货物的计费重量,取体积重量和实际重量的较大值。
o count_price 方法:根据货物类型和重量区间设置计费费率,计算每个货物的价格,并根据客户类型(个人或企业)给予折扣。
• Print 类:负责输出订单的详细信息,包括客户信息、航班信息、货物明细等。
我再带入之前的原则:
- 单一职责原则:缺点:Deal 类:包含了过多的属性和方法,如用户信息、货物列表、航班信息等。可以考虑将这些职责拆分到不同的类中,例如将用户信息单独封装到一个管理类中,货物列表封装到一个货物管理类中,以进一步简化 Deal 类的职责。
- 开闭原则:Good_type 枚举类:虽然可以通过添加新的枚举值来扩展货物类型,但 count_price 方法中需要手动添加新的逻辑。可以考虑将货物费率逻辑抽取到一个独立的类中,通过配置文件或数据库来管理费率,从而进一步实现开闭原则。
- 合成复用原则:Good 类:虽然 Good 类本身职责单一,但它的属性较多(如宽度、长度、高度、重量等)。可以考虑将这些属性封装到一个单独的类中(如 Dimension 类),并通过组合的方式在 Good 类中使用。这样可以进一步提高代码的复用性和可维护性。
这是我的代码几个还需要改进的空间。
总结:从这四个原则来看,我的代码在很多方面都做得很好,尤其是在里氏代换原则和合成复用原则的运用上。不过,还可以通过进一步拆分职责、优化扩展性和复用性来提升代码的质量。
接下来贴一下源码,希望大家多多点评和指正(顺带混下字数,虽然截止到这句话以及够了吧)
- import java.util.ArrayList;
- import java.util.Scanner;
- public class Main{
-
public static void main(String[] args) -
{ -
Scanner sc = new Scanner(System.in); -
Userkind kind = Userkind.valueOf(sc.nextLine().toUpperCase()); -
String input1 = sc.nextLine(); -
while(input1.isEmpty()) -
input1 = sc.nextLine(); -
String input2 = sc.nextLine(); -
while(input2.isEmpty()) -
input2 = sc.nextLine(); -
String input3 = sc.nextLine(); -
while(input3.isEmpty()) -
input3 = sc.nextLine(); -
String input4 = sc.nextLine(); -
while(input4.isEmpty()) -
input4 = sc.nextLine(); -
Customer customer = new Customer(input1,input4,input3,input2,kind); -
Good_type good_type = Good_type.valueOf(sc.nextLine().toUpperCase()); -
int num_good = sc.nextInt(); -
ArrayList<Good> good_list = new ArrayList<>(); -
int temp1 = num_good; -
while(temp1-- > 0){ -
int num = sc.nextInt(); -
input1 = sc.nextLine(); -
while(input1.isEmpty()) -
input1 = sc.nextLine(); -
double width = sc.nextDouble(); -
double length = sc.nextDouble(); -
double height = sc.nextDouble(); -
double weight = sc.nextDouble(); -
good_list.add(new Good(input1,width,length,height,weight,num)); -
} -
input1 = sc.nextLine(); -
while(input1.isEmpty()) -
input1 = sc.nextLine(); -
input2 = sc.nextLine(); -
while(input2.isEmpty()) -
input2 = sc.nextLine(); -
input3 = sc.nextLine(); -
while(input3.isEmpty()) -
input3 = sc.nextLine(); -
String date = sc.nextLine(); -
double max_weight = sc.nextDouble(); -
Flight flight = new Flight(input1,input2,input3,date,max_weight); -
String deal_num = sc.nextLine(); -
while(deal_num.isEmpty()) -
deal_num = sc.nextLine(); -
date = sc.nextLine(); -
String address = sc.nextLine(); -
while(address.isEmpty()) -
address = sc.nextLine(); -
String name = sc.nextLine(); -
while(name.isEmpty()) -
name = sc.nextLine(); -
String phonenum = sc.nextLine(); -
while(phonenum.isEmpty()) -
phonenum = sc.nextLine(); -
User user = new User(address,phonenum,name); -
address = sc.nextLine(); -
while(address.isEmpty()) -
address = sc.nextLine(); -
name = sc.nextLine(); -
while(name.isEmpty()) -
name = sc.nextLine(); -
phonenum = sc.nextLine(); -
while(phonenum.isEmpty()) -
phonenum = sc.nextLine(); -
User user2 = new User(address,phonenum,name); -
Pay_methods pay_methods = Pay_methods.valueOf(sc.nextLine().toUpperCase()); -
Paymethod paymethods; -
if(pay_methods == Pay_methods.ALIPAY) -
paymethods = new Alipay(); -
else if(pay_methods == Pay_methods.WECHAT) -
paymethods = new Wechatpay(); -
else -
paymethods = new Cashpay(); -
Deal deal = new Deal(customer,paymethods,num_good,good_list,date,user,user2,flight,deal_num,good_type); -
Control control = new Control(deal,customer); -
control.is_overweight(); -
control.count_weight(); -
control.count_price(); -
Print print = new Print(); -
print.display(control); -
} - }
- enum Userkind{
-
INDIVIDUAL, -
CORPORATE - }
- enum Pay_methods{
-
ALIPAY, -
WECHAT, -
CASH - }
- enum Good_type{
-
NORMAL, -
DANGEROUS, -
EXPEDITE, - }
- interface Paymethod{
-
String paymethod(); - }
- class Alipay implements Paymethod{
-
@Override -
public String paymethod() { -
return "支付宝支付金额"; -
} - }
- class Wechatpay implements Paymethod{
-
@Override -
public String paymethod(){ -
return "微信支付金额"; -
} - }
- class Cashpay implements Paymethod{
-
@Override -
public String paymethod(){ -
return "现金支付金额"; -
} - }
- class Print{
-
public static void display(Control control){ -
System.out.println("客户:"+ control.getCustomer().getName() +"(" + control.getCustomer().getPhone_number() + ")"+ "订单信息如下:"); -
System.out.println("-----------------------------------------"); -
System.out.println("航班号:"+ control.getDeal().getFlight().getFlight_number()); -
System.out.println("订单号:"+ control.getDeal().getDeal_number()); -
System.out.println("订单日期:"+ control.getDeal().getTime()); -
System.out.println("发件人姓名:"+ control.getDeal().getSender().getName()); -
System.out.println("发件人电话:"+ control.getDeal().getSender().getPhone_number()); -
System.out.println("发件人地址:"+ control.getDeal().getSender().getAddress()); -
System.out.println("收件人姓名:"+ control.getDeal().getReceiver().getName()); -
System.out.println("收件人电话:"+ control.getDeal().getReceiver().getPhone_number()); -
System.out.println("收件人地址:"+ control.getDeal().getReceiver().getAddress()); -
System.out.println("订单总重量(kg):"+ String.format("%.1f", control.getDeal().getTotal_weight())); -
System.out.println(control.getDeal().getWhich_pay().paymethod()+":"+ String.format("%.1f", control.getDeal().getTotal_price())); -
System.out.printf("\n货物明细如下:\n"); -
System.out.println("-----------------------------------------"); -
System.out.println("明细编号\t货物名称\t计费重量\t计费费率\t应交运费"); -
for(int i = 0 ; i < control.getDeal().getGood_list().size(); i++) -
{ -
Good temp = control.getDeal().getGood_list().get(i); -
System.out.printf("%d\t%s\t%s\t%s\t%s",i+1,temp.getGood_name(),String.format("%.1f",temp.getWeight_count()),String.format("%.1f",temp.getRate()),String.format("%.1f",temp.getPrice())); -
if( i +1 != control.getDeal().getGood_list().size()) -
System.out.printf("\n"); -
} -
} - }
- class Control {
-
private Deal deal; -
private Customer customer; -
public Control(Deal deal,Customer customer) -
{ -
this.deal = deal; -
this.customer = customer; -
} -
public Deal getDeal() { -
return deal; -
} -
public void setDeal(Deal deal) { -
this.deal = deal; -
} -
public Customer getCustomer() { -
return customer; -
} -
public void setCustomer(Customer customer) { -
this.customer = customer; -
} -
public void is_overweight(){ -
double count = 0; -
for(int i = 0 ; i< this.deal.getGood_list().size(); i++) -
count += this.deal.getGood_list().get(i).getWeight(); -
if(count > this.deal.getFlight().getMax_weight()) -
{ -
System.out.println("The flight with flight number:"+ this.deal.getFlight().getFlight_number()+" has exceeded its load capacity and cannot carry the order."); -
System.exit(0); -
} -
} -
public void count_weight(){ -
for(int i = 0 ; i < this.deal.getGood_list().size(); i++) -
{ -
Good temp = this.deal.getGood_list().get(i); -
double count = temp.getHeight()* temp.getLength()*temp.getWidth()/6000; -
temp.setWeight_count(Math.max(count,temp.getWeight())); -
} -
} -
public void count_price(){ -
double sum = 0; -
int[] rate_list = new int[4]; -
switch(this.deal.getGood_type()) { -
case NORMAL: { -
rate_list[0] = 35; -
rate_list[1] = 30; -
rate_list[2] = 25; -
rate_list[3] = 15; -
break; -
} -
case DANGEROUS: { -
rate_list[0] = 80; -
rate_list[1] = 50; -
rate_list[2] = 30; -
rate_list[3] = 20; -
break; -
} -
case EXPEDITE: { -
rate_list[0] = 60; -
rate_list[1] = 50; -
rate_list[2] = 40; -
rate_list[3] = 30; -
break; -
} -
} -
for(int i= 0 ;i< this.deal.getGood_num(); i++) -
{ -
Good temp = this.deal.getGood_list().get(i); -
if(temp.getWeight_count() < 20) -
temp.setRate(rate_list[0]); -
else if(temp.getWeight_count() < 50 && temp.getWeight_count() >= 20) -
temp.setRate(rate_list[1]); -
else if(temp.getWeight_count() < 100 && temp.getWeight_count() >= 50) -
temp.setRate(rate_list[2]); -
else{ -
temp.setRate(rate_list[3]); -
} -
temp.setPrice(temp.getRate()*temp.getWeight_count()); -
sum += temp.getPrice(); -
} -
if(this.deal.getCustomer().getKind() == Userkind.INDIVIDUAL) { -
this.deal.setTotal_price(sum * 0.9); -
} -
else if (this.deal.getCustomer().getKind() == Userkind.CORPORATE) { -
this.deal.setTotal_price(sum * 0.8); -
} -
} - }
- class User{
-
private final String address; -
private final String phone_number; -
private final String name; -
public User(String address ,String phone_number,String name) -
{ -
this.address = address; -
this.phone_number = phone_number; -
this.name = name; -
} -
public String getAddress() { -
return address; -
} -
public String getPhone_number() { -
return phone_number; -
} -
public String getName() { -
return name; -
} - }
- class Customer extends User{
-
private final Userkind kind; -
private final String User_number; -
public Customer(String User_number,String address,String phone,String name,Userkind kind) -
{ -
super(address,phone,name); -
this.User_number = User_number; -
this.kind = kind; -
} -
public String getUser_number() { -
return User_number; -
} -
public Userkind getKind() { -
return kind; -
} - }
- class Good{
-
private int Num; -
private String good_name; -
private double width; -
private double length; -
private double height; -
private double weight; -
private double weight_count; -
private double rate; -
private double price; -
public Good(String name,double width,double length,double height,double weight,int num) -
{ -
this.good_name = name; -
this.width = width; -
this.length = length; -
this.height = height; -
this.weight = weight; -
this.weight_count = 0 ; -
this.rate = 0 ; -
this.price = 0 ; -
this.Num = num; -
} -
public String getGood_name() { -
return good_name; -
} -
public void setGood_name(String good_name) { -
this.good_name = good_name; -
} -
public double getWidth() { -
return width; -
} -
public void setWidth(double width) { -
this.width = width; -
} -
public double getLength() { -
return length; -
} -
public void setLength(double length) { -
this.length = length; -
} -
public double getHeight() { -
return height; -
} -
public void setHeight(double height) { -
this.height = height; -
} -
public double getWeight() { -
return weight; -
} -
public void setWeight(double weight) { -
this.weight = weight; -
} -
public double getWeight_count() { -
return weight_count; -
} -
public void setWeight_count(double weight_count) { -
this.weight_count = weight_count; -
} -
public double getRate() { -
return rate; -
} -
public void setRate(double rate) { -
this.rate = rate; -
} -
public double getPrice() { -
return price; -
} -
public void setPrice(double price) { -
this.price = price; -
} -
public int getNum() { -
return Num; -
} -
public void setNum(int num) { -
Num = num; -
} - }
- class Flight{
-
private String flight_number; -
private String start_address; -
private String end_address; -
private String time; -
private double max_weight; -
public Flight(String flight_number,String start,String end,String time,double max) -
{ -
this.flight_number = flight_number; -
this.start_address = start; -
this.end_address = end; -
this.time = time; -
this.max_weight = max; -
} -
public String getFlight_number() { -
return flight_number; -
} -
public void setFlight_number(String flight_number) { -
this.flight_number = flight_number; -
} -
public String getStart_address() { -
return start_address; -
} -
public void setStart_address(String start_address) { -
this.start_address = start_address; -
} -
public void setEnd_address(String end_address) { -
this.end_address = end_address; -
} -
public String getEnd_address() { -
return end_address; -
} -
public double getMax_weight() { -
return max_weight; -
} -
public void setMax_weight(int max_weight) { -
this.max_weight = max_weight; -
} -
public String getTime() { -
return time; -
} -
public void setTime(String time) { -
this.time = time; -
} - }
- class Deal{
-
private final Customer customer; -
private User sender; -
private User receiver; -
private String time; -
private Paymethod which_pay; -
private int good_num; -
private ArrayList<Good> good_list; -
private Flight flight; -
private double total_price; -
private String deal_number; -
private final Good_type good_type; -
public Deal(Customer customer,Paymethod pay,int num,ArrayList<Good> good_list,String time,User sender,User receiver,Flight flight,String deal_number,Good_type type) -
{ -
this.customer = customer; -
this.which_pay = pay; -
this.good_num = num; -
this.good_list = good_list; -
this.time = time; -
this.sender = sender; -
this.receiver = receiver; -
this.flight = flight; -
this.total_price = 0; -
this.deal_number = deal_number; -
this.good_type = type; -
} -
public Paymethod getWhich_pay() { -
return which_pay; -
} -
public void setWhich_pay(Paymethod which_pay) { -
this.which_pay = which_pay; -
} -
public int getGood_num() { -
return good_num; -
} -
public void setGood_num(int good_num) { -
this.good_num = good_num; -
} -
public ArrayList<Good> getGood_list() { -
return good_list; -
} -
public void setGood_list(ArrayList<Good> good_list) { -
this.good_list = good_list; -
} -
public User getSender() { -
return sender; -
} -
public void setSender(User sender) { -
this.sender = sender; -
} -
public User getReceiver() { -
return receiver; -
} -
public void setReceiver(User receiver) { -
this.receiver = receiver; -
} -
public Flight getFlight() { -
return flight; -
} -
public void setFlight(Flight flight) { -
this.flight = flight; -
} -
public double getTotal_price() { -
return total_price; -
} -
public void setTotal_price(double total_price) { -
this.total_price = total_price; -
} -
public String getDeal_number() { -
return deal_number; -
} -
public void setDeal_number(String deal_number) { -
this.deal_number = deal_number; -
} -
public double getTotal_weight() { -
double total_weight = 0; -
for(int i = 0 ; i < good_num ; i++) -
{ -
total_weight += good_list.get(i).getWeight_count(); -
} -
return total_weight; -
} -
public String getTime() { -
return time; -
} -
public void setTime(String time) { -
this.time = time; -
} -
public Customer getCustomer() { -
return customer; -
} -
public Good_type getGood_type() { -
return good_type; -
} - }

浙公网安备 33010602011771号