java

面向对象程序设计—第二次总结性Blog

前言

      对几周学习的内容,由本次博客来进行一个总结。

      1.随着学期尾声的不断接近,作业的难度也逐渐回落,但电信收费系统的难度有点让人无从下手,感觉java的残酷在这个系列题上尽数体现了。最近的几次作业,所涉及的知识点仍然包含正则表达式、继承与多态还有抽象类与接口、集合框架等等。从题量上来说不是很大,但是难度比较大。有时候花几个小时做不出一道题目。

      2.对于课程来说,主要讲解了javafx和集合框架,javafx相对于集合框架来说比较简单。

      3.集合框架的内容虽然不会考,但是其实也会有所涉及,就像ArrayList和HashSet其实都是经常使用的。

·让我对类的聚合关系理解更加深刻,还有类的继承和多态,本次考察主要向我们渗透了一些关于Java的设计原则,让我们能更加深刻的思考类与类之间的关系,从而深入的了解面向对象的设计原则,这些都是这三次习题集考察的亮点。

第四次作业——题目集04 7-1

      难度:偏大    

  整体思路分析

类图:

      

  度量分析

      圈复杂度54,可以看出来这题的难度很大,代码质量很差。

      

   核心代码分析

      下面是对点是否冗杂的判断,先看有没有点重复,将不重复的点加入ArrayList中,然后再对其中的点进行是否在一条边上的判断。


· 设计与分析:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.*;
public class Main {
public static void main(String[] args) {
Menu menu = new Menu(new Dish[]{new Dish("西红柿炒蛋", 15),new Dish("清炒土豆丝", 12),new Dish("麻婆豆腐", 12),new Dish("油淋生菜", 9)});
Order order = new Order();
List<String> notFounds = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
dowhile (scanner.hasNextLine()) {
String line = scanner.nextLine();
if ("end".equals(line)) {
break;
}
String[] lineArray = line.split(" ");
String dishName = lineArray[0];
int portion = Integer.parseInt(lineArray[1]);
Dish dish = menu.searthDish(dishName);
if (dish == null) {
notFounds.add(dishName);
} else {
order.addARecord(dish, portion);
}
}

for (String dishName : notFounds) {
System.out.println(dishName + " does not exist");
}

System.out.println(order.getTotalPrice());
}
}
class Dish {
String name;//菜品名称
int unit_price; //单价
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getUnit_price() {
return unit_price;
}
public void setUnit_price(int unit_price) {
this.unit_price = unit_price;
}
public Dish(String name, int unit_price) {
this.name = name;
this.unit_price = unit_price;
}
//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
int getPrice(int portion)
{
float b[] = {1, 1.5f, 2};
return Math.round((unit_price * b[portion - 1]));
}
}
class Menu {
private Dish[] dishs;//菜品数组,保存所有菜品信息

Menu(Dish[] dishs) {
this.dishs = dishs;
}

Dish searthDish(String dishName) {
for (Dish dish : dishs) {
if (dish.getName().equals(dishName)) {
return dish;
}
}
return null;
}
}
class Record {
Dish d;//菜品
int portion;//份额(1/2/3代表小/中/大份)

public Dish getD() {
return d;
}

public void setD(Dish d) {
this.d = d;
}

public int getPortion() {
return portion;
}

public void setPortion(int portion) {
this.portion = portion;
}

public Record(Dish d, int portion) {
this.d = d;
this.portion = portion;
}

//计价,计算本条记录的价格
int getPrice()
{
return d.getPrice(portion);
}
}
class Order {
private List<Record> records = new ArrayList<>();//保存订单上每一道的记录

//计算订单的总价
int getTotalPrice()
{
int sum = 0;
for (Record record : records) {
sum += record.getPrice();
}
return sum;
}

//添加一条菜品信息到订单中。
Record addARecord(Dish dish, int portion) {
Record record = new Record(dish, portion);
records.add(record);
return record;
}
}

本代码为题目集二7-2,本题题目由0、1组成的二进制数据流,我对这道题的每一步基本都有Blog,操作的时候很困难,起初不知道怎么编程,后面看书和在网上查找像是问题,并问了些同学,得以解决。

此题大部分运用数组并对数组中数据的查找,数组的储存,中字符串的调用,输出等等。

下面是我从网上寻找的降低圈复杂度的方法,在今后的学习或者在解决PTA题目时会学着慢慢的渗透和尝试降低圈复杂度的方法。

Composing Methods(重新组织你的函数)

Extract Method(提炼函数)

Substitute Algorithm(替换你的算法)

第五次作业——题目集05 7-1

      难度:偏大 

类图:

要求为抽象类,隐藏属性。增加了一个平面的类。其他与第一题大致相同。所以也看图写话。但是抽象类和抽象方法我不是很懂,当时也没有正确使用这个类和方法,导致空写了一个abstract类。

分析图:

图表数据看起来还是很不错的,继续保持。


 

核心代码分析


import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;


public class Main {
public static void main(String[] args) {
Menu menu = new Menu();
Order order = new Order(menu);
Scanner scanner = new Scanner(System.in);
String line = scanner.nextLine();
while (!line.equals("end")) {
String[] lineArray = line.split(" ");


if (lineArray.length > 2) {
int orderNum = Integer.parseInt(lineArray[0]);
String dishName = lineArray[1];
int portion = Integer.parseInt(lineArray[2]);
int num = Integer.parseInt(lineArray[3]);
order.addARecord(orderNum, dishName, portion, num);
} else if ("delete".equals(lineArray[1])) {
order.delARecordByOrderNum(Integer.parseInt(lineArray[0]));
} else {
menu.addDish(lineArray[0], Integer.parseInt(lineArray[1]));
}


line = scanner.nextLine();
}


System.out.println(order.getTotalPrice());
}
}


class Menu {
private List<Dish> dishs = new ArrayList<>();//菜品数组,保存所有菜品信息


void addDish(Dish dish) {
}


Menu() {


}


Dish searthDish(String dishName) {
for (Dish dish : dishs) {
if (dish.getName().equals(dishName)) {
return dish;
}
}
return null;
}


//添加一道菜品信息
Dish addDish(String dishName, int unit_price) {
for (Dish dish : dishs) {
if (dish.getName().equals(dishName)) {
dish.setUnit_price(unit_price);
return dish;
}
}
Dish dish = new Dish(dishName, unit_price);
dishs.add(dish);
return dish;
}
}


class Dish {
String name;//菜品名称
int unit_price; //单价


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


public int getUnit_price() {
return unit_price;
}


public void setUnit_price(int unit_price) {
this.unit_price = unit_price;
}


public Dish(String name, int unit_price) {
this.name = name;
this.unit_price = unit_price;
}


public Dish() {
}


//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
int getPrice(int portion) {
float b[] = {1, 1.5f, 2};
return Math.round((unit_price * b[portion - 1]));
}
}


class Record {
private int orderNum;//序号\
private Dish d;//菜品\
private int portion;//份额(1/2/3代表小/中/大份)\
private int num;
private boolean isDelete = false;


public boolean isNotFound() {
return notFound;
}


public void setNotFound(boolean notFound) {
this.notFound = notFound;
}


private boolean notFound = false;


public Record(Dish d, int portion) {
this.d = d;
this.portion = portion;
}


public Record(int orderNum, Dish d, int portion, int num) {
this.orderNum = orderNum;
this.d = d;
this.portion = portion;
this.num = num;
}


//计价,计算本条记录的价格
int getPrice() {
return d.getPrice(portion) * this.num;
}


public int getOrderNum() {
return orderNum;
}


public void setOrderNum(int orderNum) {
this.orderNum = orderNum;
}


public Dish getD() {
return d;
}


public void setD(Dish d) {
this.d = d;
}


public int getPortion() {
return portion;
}


public void setPortion(int portion) {
this.portion = portion;
}


public boolean isDelete() {
return isDelete;
}


public void setDelete(boolean delete) {
isDelete = delete;
}


public int getNum() {
return num;
}


public void setNum(int num) {
this.num = num;
}
}


class Order {
private Menu menu;


private static List<Record> records = new ArrayList<>();//保存订单上每一道的记录


public Order(Menu menu) {
this.menu = menu;
}


//计算订单的总价
int getTotalPrice() {
int sum = 0;
for (Record record : records) {
int price = record.getPrice();
if (!record.isDelete()) {
sum = sum + price;
}
}


return sum;
}


//添加一条菜品信息到订单中。
Record addARecord(int orderNum, String dishName, int portion, int num) {
Dish dish = menu.searthDish(dishName);
if (dish == null) {
System.out.println(dishName + " does not exist");
return null;
}
Record record = new Record(orderNum, dish, portion, num);
records.add(record);
int price = record.getPrice();
System.out.println(record.getOrderNum() + " " + record.getD().getName() + " " + price);
return record;
}


public boolean delARecordByOrderNum(int orderNum) {
for (Record record : records) {
if (!record.isNotFound() && !record.isDelete() && record.getOrderNum() == orderNum) {
record.setDelete(true);
return true;
}
}
System.out.println("delete error;");
return false;
}
}

 

本代码为题目集五7-1,此题因为时间问题和知识运用不够熟练,并没在pta联系中提交,有后余时间将其完成。本题考察点与线间的距离运算问题,本题目与数学结合,难度为输入数字正确进入相应判断运行公式中,正确输出,建立不同的数据类型,调用建立函数,进入计算运行,其他问题为情况不符合情况,判断问题的否定输出等等。本题出现多次Blog,多次看书,在网上查找学习资料,学习,了解,最后进行编程。

期中考试——题目集

      难度:中等

  整体思路分析

      7-1 测验1-圆类设计

      7-2 测验2-类结构设计

      7-3 测验3-继承与多态

      7-4 测验4-抽象类与接口

      题目集 期中考试已经被大大的降低了难度,题目已经给出了各个板块的类图

类图:

 

  度量分析

      从度量分析中其实可以看出来相比于题目集题的平均复杂度已经变小了,但整体的代码依旧可用性不高。

      

  核心代码分析

      

 

其难度在于第二题的课程成绩统计程序。

  采坑分析

      在写这个题目的时候,出现了我写题目集06 7-1没有出现过的情况。在题目集96 7-1中对于区号我是再使用一遍正则表达式来进行提取。其实这样没错,但在区别区号是否在省内的时候,我是使用了matcher.find()这个方法来进行识别,即若匹配到(079[2-9])|(0701)中的一个就为true,但经过调试我发现,这个方法只会进行一次,在之后就变成了false,在之后我就修改了我的代码,先将其转化为整形数,再进行比较。

  改进建议

      在正则表达式上可以更加的简略一些,可以将regex1和regex4写成一个正则表达式,同理匹配通话记录的也是这样,这样可以大大的减少代码的复杂性。在另一方面,其实可以不需要按照题目所给类图这样来进行代码编写,因为我发现在通过所有测试点之后依旧有一些方法是从来没有使用过的。这会显的代码十分的复杂,提高了代码量,应该想办法改变这一过程。

  度量分析

      

  核心代码分析

      

 

 

 本题最主要就是对于数字,字符,空格,英文逗号,英文句号组成的短信进行正则表达式的匹配。

  • 采坑心得

1.在设计类时,圈复杂度较大,在今后我将学习如何将圈复杂度降低。

2.在交到pta上的时候我的代码出现了得分不满的问题,但是在其他编译器上可以进行编辑,是因为我考虑少了情况,没有多方面考虑,如题目集一的第四题,for的循环类型建立不足,导致正确结构无法全部输出,所以在日后我要考虑多种情况的发生

3.类与类之间会有相互调用的现象,这也增加了类与类之间的耦合性,怎样减少代码的类与类之间的关系及其耦合性,是我今后要学习的主要的进取方向,在减少类与类的耦合性的同时,也达到了我们设计代码的目的,也满足了程序的设计原则。

4.类与类之关系,以及怎样更好的减少类与类之间的关系,在设计代码时,我设计的两个类总是有很多的关联,子类继承父类的功能,这些关系我在解题时依然不清楚。

5.本次作业,我个人进步最大的地方是学习了几个设计模式来辅助自己设计,这让我代码整体结构比较好,思路清晰,逻辑严谨。这次作业我也学到了多线程编程的基本方法。

  • 改进建议

1.在main 函数里进行输入和判断,还有switch case case对应选项,然后调用选项对应方法不同的方法,但在Main类里写上5个方法对应五个选项,这样会更有条理;

2.在输入数据的格式判断,数据的parse,判断点输入错误,判断线输入错误,输出数据用不同的类在执行,职责单一,内聚高;

3.代码太长,主要原因就是在写选项的时候是一个一个一个写,这里可以怎么改呢?可以通过使用switch语句去指定进行输出,甚至可以对数据进行统一的计算处理,再进行一一对应到switch中,这样可以大幅降低复杂度,代码运行的效率更高。若是想处理的更为体现类的形式,可以将数据计算处理在一个计算类中,判断条件写在判断类中,结果输出写在一个输出类中,这样可以将题目处理的更有可读性。

4.在写三角形的方法时,算三边的长度诶个方法都算代码复用率太高,其实这里可以吧三线作为三角形的数据成员;

  • 总结:

    PTA中题集和期中考试的习题让我收获很多

    1.对于scanner类用法有了更清晰认知;

    2.对于集合arraylisty有了初步的了解;

    3.对于抽象类abstract有了更深入的理解和应用;

    4.对题目的分析应该更加快速和高效,然后就是代码实现不够熟练;

    5.类的创建的对象的构造以及方法的调用都是有所进步的,我还学到了正则表达式的运用,类的关系都有所进步。

    6.在接下来的学习中,我深刻的认识到我需要学习的东西有很多,首先是对正则表达式的系统学习,在这次作业中,我非常快速的学了正则表达式,只是表面的很肤浅的,只会简单的运用,所以接下来我要进行系统的学习,在之后的作业中可以的得心应手的运用来判断字符的格式;其次我要更加深入的学习类和对象的创建,因为通过这次作业,我发现,我虽然知道是要用到类,但是运用不熟练,他们之间的运用也非常不熟练,对象传参也不熟练,而且我知道创建类和对象是提高代码的复用率,但是我的代码在建了类和对象之后并没有变得简单很多,而是越写越复杂,可能对类的本质还不太了解;最后我学到debug,也就是设断点,单步调试,一些并不是显而易见的逻辑错误通过单步调试来看到对写代码特别有好处。我接下来要学习的是一些基本的String类里的方法熟练运用,我发现我在写这些方法的时候并不是很熟练,而是要用一种只会用一种。

    7.对于注释我有了新的理解,真的可以帮助我分析并且理清我的思路;

 

posted @ 2022-04-10 03:45  九又四分之三  阅读(51)  评论(0)    收藏  举报