前言
之前所涉及知识点如下:
类与类之间的关系、类设计的原则、一些常见的类等
题量在可接受范围之内
正文
第二次雨刷问题

设计与分析:
本次我们首次使用类来编写代码,并引入了业务类和实体类的概念。我通过雨刷的功能编写了Lever、Wiper、Dial三个实体类,并编写了Control这个业务类来调控这三个实体类。通过驾驶员的信息输入编写了HandsOfDriver和EyesOfDriver两个类,目的是想做出雨刷模拟系统的感觉。
踩坑心得:
没有深刻理解类间关系,耦合性太高。
改进建议:
HandsOfDriver应该通过Control来和Lever、Wiper、Dial三个实体类进行交流
第三次雨刷问题

设计与分析:
利用private对各个类进行了封装,提高了安全性。其他类与Lever、Wiper、Dial三个实体类不再是直接交流,而通过Control这个媒介,使得结构更加严谨,便于以后维护和更新。
踩坑心得:
Main中包含的内容太多了,而且Control只将一部分类联系起来了。
改进建议:
将Main中的的功能转移到Control中,将更多类通过Control联系起来。
第四次雨刷问题

设计与分析:
本次尝试用单例模式来避免重复创建对象的行为,此处我用的是懒汉模式。
踩坑心得:
前期没有理解单例模式的意义和使用,绕了很多弯子;没有注意线程的安全性,并发性差。
改进建议:
在方法上加锁或对类对象加锁。
第五次雨刷问题

设计与分析:
本次采用继承来增强代码的扩展性。我设计了Driver、Dial、Brush、Lever、Control五个抽象父类来初步得确立了各个类基本的方法,之后我设计了DriverType1、DialType1、BrushType1、LeverType1、ControlType1作为其子类,并对父类的抽象方法进行了重写,同时也为了各个类的扩展提供了可能性。
踩坑心得:
一开始没有将super放在第一句导致报错
改进建议:
设计更多不同种类的子类来加深对继承意义的理解
PTA题目集
设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:

设计与分析:
此题给出了相关类图,限制了做题空间。Day、Year、Month作为成员变量存在于DateUtil中,因此Day、Year、Month与DateUtil是聚合关系。我的思路是先编写Day、Year、Month这几个实体类,各个击破,因为Day、Year、Month这几个实体类之间的联系不大。之后编写DateUtil,将Day、Year、Month这几个实体类联系起来。
踩坑心得:
没有进行边界值测试,如月初、月底、年初、年底,导致几个点迟迟过不了。
改进建议:
下次不仅要测试题目中给的例子,也要通过其他不同的数值进行测试,精准找到问题之所在。
PTA题目集
本程序仅用于为学生所玩的游戏提供正确答案的功能,即根据学生得到的卡片种类与数量,给出 排序前和排序后的卡片顺序,同时给出所有卡片的面积之和。

设计与分析:
此题给出了相关类图,限制了做题空间。整个结构层层推进,Shape是一个抽象父类,Trapezoid、Triangle、Rectangle、Circle 是 Shape 的子类。我首先从Shape入手,再编写Trapezoid、Triangle、Rectangle、Circle 类,再一层一层往上逆推,最终完成整个架构的建立。
踩坑心得:
一开始并没有考虑到CompareTo这个接口的作用
改进建议:
要学会读懂类图,并从整体上设计类
总结
知识点:
MVC设计模式,即M:Model (实体类,Entity)、V:View (接口类,GUI)、C:Controller (控制类,Control)
类与类的关系:
依赖关系(Dependency)、关联关系(Association)、聚合关系(Aggregation)、组合关系(Composition)、继承关系(泛化关系 Generalization)、实现关系(Realization)
区分类与类之间的关系:要从语义上而不是语法上。
耦合性强弱:组合 > 聚合 > 关联 > 依赖
继承关系:
class 子类 extends 父类 {}
super:
1.子类想用到父类的东西时,需要用到super.
2.在子类构造方法的第一行(只能)用super()调用父类对应的构造方法为了创建子类对象时,先初始化父类型特征
abstract抽象类:
抽象类不能实例化对象,抽象方法需要在子类中@Override复写。如果名称不一致 也没有写override 则会在不报错
类的设计原则:
单一职责原则:一个类只负责一项职责
迪米特法则:1.不要和陌生人说话(实体类之间一般都是陌生人) 2.只和你的直接朋友通信 3.最少知识原则
里氏替换原则:子类可以扩展父类的功能,但不能改变父类原有的功能
合成复用原则:在软件复用时,要尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现
依赖倒置原则:要依赖抽象,不要依赖具体 要依赖接口,不要依赖编程
开闭原则:一个软件实体如类,模块和函数应该对扩展开放,对修改关闭
接口隔离原则:一个接口里的方法越少越好(所以一个接口就一个方法)
接口:
public interface 父类{}
class 子类 implements 父类1,父类2...{}
应用场合:对于行为/方法的抽象,区别抽象类(对于实体的抽象)
特点:支持多继承
2.容器
(1)Array
String[] array = {}
//输出
for(String data:array){
Systrm.out.print(data + " ");
}
System.out.println("")
//排序(升序)
java.util.Arrays.sort(array);
(2)list
定义:ArrayList list = new ArrayList();//查找数据时用 LinkedList list = new LinkedList();//增删时用
泛型:把类型做参数 LinkedList<Integer> list = new LinkedList()<Integer>;
输出:for(int i = 0; i < list.size();i ++){ }
//排序(升序)
java.util.Collections.sort(list1);
列表中是实型,整型,字符串可用
若类列表要用,要调用方法
java.util.Collections.sort()
(3)String StringBuffer StringBuilder
字符串连接效率: StringBuilder > StringBuffer > String
涉及变长字符串用StringBuilder、StringBuffer,在涉及多线程用StringBuffer
System.out.println(str1==str3)->true//地址相同
System.out.println(str2==str3)->true
String Builder sb1 = new StringBuilder("abc");
sb1.append("123")
System.out.println(sb1.toString());->abc123//转成字符串输出
八种基本变量类型:
int long short char float double byte boolean
一些修饰符:
private public protected default static final(不能继承) abstract class interface extends implements Object(Object类是所有类的父类) this super
测试方法/技术:
1.边界值测试
程序的缺陷往往容易发生在输入数据的边界
健壮性边界值测试
2.等价类测试
等价关系:自反关系、反对称关系、传递关系
划分子集的依据就是等价关系,之后的子集叫做等价
类的设计原则:
简单工厂模式、工厂方法模式、抽象工厂模式等
多态:
不同的对象接收到同一消息产生不同的操作
1.Circle circle = new Circle("black",3.24);
2.Circle.getArea();
3.hape shape = new Circle(); 子类的对象赋给父类类型是可行的
4.System.out.println(shape.getArea());
5.Shape = new Ball("BLACK", 5.4);
6.System.out.println(shape.getArea());
第四行与第六行 两段相同的代码 输出的结果不同
部分代码如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int year = 0;
int month = 0;
int day = 0;
int choice = input.nextInt();
if (choice == 1) { // test getNextNDays method
int m = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
DateUtil date = new DateUtil(year, month, day);
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}
m = input.nextInt();
if (m < 0) {
System.out.println("Wrong Format");
System.exit(0);
}
System.out.print(date.getYear().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " next " + m + " days is:");
System.out.println(date.getNextNDays(m).showDate());
} else if (choice == 2) { // test getPreviousNDays method
int n = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
DateUtil date = new DateUtil(year, month, day);
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}
n = input.nextInt();
if (n < 0) {
System.out.println("Wrong Format");
System.exit(0);
}
System.out.print(
date.getYear().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " previous " + n + " days is:");
System.out.println(date.getPreviousNDays(n).showDate());
} else if (choice == 3) { //test getDaysofDates method
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
int anotherYear = Integer.parseInt(input.next());
int anotherMonth = Integer.parseInt(input.next());
int anotherDay = Integer.parseInt(input.next());
DateUtil fromDate = new DateUtil(year, month, day);
DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);
if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
System.out.println("The days between " + fromDate.showDate() +
" and " + toDate.showDate() + " are:"
+ fromDate.getDaysofDates(toDate));
} else {
System.out.println("Wrong Format");
System.exit(0);
}
}
else{
System.out.println("Wrong Format");
System.exit(0);
}
}
}
class DateUtil {
private Year year = new Year();
private Month month = new Month();
private Day day = new Day();
private int[] mon_maxnum = { 31,28,31,30,31,30,31,31,30,31,30,31};
public DateUtil() {
}
public DateUtil(int y, int m, int d) {
this.year.setValue(y);
this.month.setValue(m);
this.day.setValue(d);
}
public Year getYear() {
return year;
}
public void setYear(Year year) {
this.year = year;
}
public Month getMonth() {
return month;
}
public void setMonth(Month month) {
this.month = month;
}
public Day getDay() {
return day;
}
public void setDay(Day d) {
this.day = day;
}
public void setDayMin() {
this.day.setValue(1);
}
public void setDayMax() {
if(this.year.isLeapYear(this.month.getValue())) {
mon_maxnum[1] = 29;
}
this.day.setValue(mon_maxnum[this.month.getValue()-1]);
mon_maxnum[1] = 28;
}
public boolean checkInputValidity() {
boolean validate0;
if(year.isLeapYear(year.getValue())) {
mon_maxnum[1] = 29;
}
if(this.month.getValue() >= 1 && this.month.getValue() <= mon_maxnum[this.month.getValue() - 1]) {
validate0 = true;
}
else {
validate0 = false;
}
mon_maxnum[1] = 28;
boolean validate1 = false;
if(validate0 && this.month.validate() && this.year.validate()) {
validate1 = true;
}
return validate1;
}
public boolean compareDates(DateUtil date) {
boolean compare = false;
if(this.year.getValue() < date.year.getValue()) {
compare = true;
}
else if(this.year.getValue() == date.year.getValue()){
if(this.month.getValue() < date.month.getValue()) {
compare = true;
}
else if(this.month.getValue() == date.month.getValue()) {
if(this.day.getValue() < date.day.getValue()) {
compare = true;
}
}
}
return compare;
}
public boolean equalTwoDates(DateUtil date) {
boolean equal = false;
if(this.year.getValue() == date.year.getValue() && this.month.getValue() == date.month.getValue() && this.day.getValue() == date.day.getValue()) {
equal = true;
}
return equal;
}
public String showDate() {
return this.year.getValue() + "-" + this.month.getValue() + "-" + this.day.getValue();
}
public DateUtil getNextNDays(int n) {
int year = this.year.getValue(), month = this.month.getValue(), day = this.day.getValue();
int[] monthTable= { 31,28,31,30,31,30,31,31,30,31,30,31};
if(this.year.isLeapYear(year)) {
monthTable[1]=29;
}
day += n;
if(n>monthTable[month-1]-day) {
do{
day -= monthTable[month-1];
month++;
if(month>12) {
month = 1;
year++;
if(this.year.isLeapYear(year)) {
monthTable[1]=29;
}
else {
monthTable[1]=28;
}
}
}while(day>monthTable[month-1]);
}
return new DateUtil(year,month,day);
}
public DateUtil getPreviousNDays(int n) {
int year = this.year.getValue(), month = this.month.getValue(), day = this.day.getValue();
int[] monthTable= { 31,28,31,30,31,30,31,31,30,31,30,31};
if(this.year.isLeapYear(year)) {
monthTable[1]=29;
}
day -= n;
while(day<=0) {
if(month==1) {
month = 12;
year--;
if(this.year.isLeapYear(year)) {
monthTable[1]=29;
}
else {
monthTable[1]=28;
}
day += monthTable[11];
}
else {
day += monthTable[month-2];
month --;
}
}
return new DateUtil(year,month,day);
}
public int getDaysofDates(DateUtil date) {
DateUtil i = this;
int n = 0;
if(equalTwoDates(date)) {
}
else {
if(compareDates(date)) {
while(i.year.getValue() != date.year.getValue() || i.month.getValue() != date.month.getValue() || i.day.getValue() != date.day.getValue()){
n++;
i = getNextNDays(n);
}
}
else {
while(i.year.getValue() != date.year.getValue() || i.month.getValue() != date.month.getValue() || i.day.getValue() != date.day.getValue()){
n++;
i = getPreviousNDays(n);
}
}
}
return n;
}
}
class Day {
private int value;
public Day() {
}
public Day(int Value) {
this.value = Value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public void dayIncrement() {
this.value++;
}
public void dayReduction() {
this.value--;
}
}
class Month {
private int value;
public Month() {
}
public Month(int Value) {
this.value = Value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public void resetMin() {
this.value = 1;
}
public void resetMax() {
this.value = 12;
}
public boolean validate() {
boolean validate;
if(value>=1&&value<=12) {
validate=true;
}
else {
validate=false;
}
return validate;
}
public void monthIncrement() {
this.value++;
}
public void monthReducton() {
this.value--;
}
}
class Year {
private int value;
public Year() {
}
public Year(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public boolean isLeapYear(int year) {
boolean isLeapYear;
if(year%400==0)
isLeapYear=true;
else
{
if(year%4==0)
{
if(year%100!=0)
isLeapYear=true;
else
isLeapYear=false;
}
else
isLeapYear=false;
}
return isLeapYear;
}
public boolean validate() {
boolean validate = false;
if(value >= 1820 && value <= 2020) {
validate = true;
}
return validate;
}
public void yearIncrement() {
this.value++;
}
public void yearReduction() {
this.value--;
}
}
浙公网安备 33010602011771号