阶段总结
JAVA第一次Blog作业
一:前言
1.知识点:
题目集01:共有4道题目,考察内容为类的设计及一元二次方程的计算和日期的计算。
题目集02:共有9道题目,题量较大,难度适中。主要考察字符串的解析及浮点数的输出和运算,if else条件语句,和for循环语句。
题目集03:共3道题目,重点考察字符串,数字与字母的转换以及String的格式判断以及内容提取。
题目集04:共2道题目,难度较大,主要考察类的设计和ArrayList及泛型的运用。
2.题量和难度:
总的来说题量和难度适中,题目也契合阶段性的java学习,考察内容精确,题目量合理,属实是不可多得的好题目集。每次作业都在引导我们更多的了解java这门语言,同时也锻炼了学生的耐❤和细❤。这几次作业各有千秋,题目集04和01的类设计均给出了具体的类图,也让我们能从中学习到合理且正规的类设计 。
二.设计与分析
1.题目集01的7-4题:日期类设计
参考题目集二中和日期相关的程序,设计一个类DateUtil,该类有三个私有属性year、month、day(均为整型数),其中,year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 除了创建该类的构造方法、属性的getter及setter方法外,需要编写如下方法:
public boolean checkInputValidity();//检测输入的年、月、日是否合法
public boolean isLeapYear(int year);//判断year是否为闰年
public DateUtil getNextNDays(int n);//取得year-month-day的下n天日期
public DateUtil getPreviousNDays(int n);//取得year-month-day的前n天日期
public boolean compareDates(DateUtil date);//比较当前日期与date的大小(先后)
public boolean equalTwoDates(DateUtil date);//判断两个日期是否相等
public int getDaysofDates(DateUtil date);//求当前日期与date之间相差的天数
public String showDate();//以“year-month-day”格式返回日期值
应用程序共测试三个功能:
1.求下n天
2.求前n天
3.求两个日期相差的天数
输出格式:
- 当输入有误时,输出格式如下:
Wrong Format - 当第一个数字为1且输入均有效,输出格式如下:
year1-month1-day1 next n days is:year2-month2-day2 - 当第一个数字为2且输入均有效,输出格式如下:
year1-month1-day1 previous n days is:year2-month2-day2 - 当第一个数字为3且输入均有效,输出格式如下:
The days between year1-month1-day1 and year2-month2-day2 are: -
以下为main函数外的各类:
class DateUtil { private Year year; private Month month; private Day day; private int[] mon_maxnum = {31,28,31,30,31,30,31,31,30,31,30,31}; 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 day) { this.day = day; } public DateUtil(int year, int month, int day) { super(); this.year = new Year(year); this.month = new Month(month); this.day = new Day(day); } public void setDayMin() { day.setValue(1); } public void setDayMax() { day.setValue(mon_maxnum[month.getValue()-1]); } public boolean checkInputValidity() { if(year.getValue()>=1820&&year.getValue()<=2020&&month.getValue()>=1&&month.getValue()<=12) { if(year.isLeapYear()) mon_maxnum[1] = 29; if(day.getValue()>=0 && day.getValue() <=mon_maxnum[month.getValue()]) { mon_maxnum[1] = 28; return true; } else { mon_maxnum[1] = 28; return false; } } else return false; } public DateUtil getNextNDays(int n) { while(n-- != 0) { if(year.isLeapYear()) mon_maxnum[1] = 29; else mon_maxnum[1] = 28; if(day.getValue() == mon_maxnum[month.getValue() - 1]) { if(month.getValue() == 12) { month.resetMin(); day.setValue(1); year.yearIncrement(); } else { month.monthIncrement();; day.setValue(1); } } else day.dayIncrement(); } return new DateUtil(year.getValue(),month.getValue(),day.getValue()); } public DateUtil getPreviousNDays(int n) { while(n-- != 0) { if(year.isLeapYear()) mon_maxnum[1] = 29; else mon_maxnum[1] = 28; if(day.getValue() == 1) { if(month.getValue() == 1) { month.resetMax(); day.setValue(mon_maxnum[11]); year.yearReduction(); } else { month.monthReduction(); day.setValue(mon_maxnum[month.getValue() - 1]); } } else day.dayReduction(); } return new DateUtil(year.getValue(),month.getValue(),day.getValue()); } public boolean equalTwoDates(DateUtil date) { if(year.getValue()==date.year.getValue()&&month.getValue()==date.month.getValue()&&day.getValue()== date.day.getValue()) return true; else return false; } public boolean compareDates(DateUtil date) { if(year.getValue() > date.year.getValue()) { return true; } else if(year.getValue() == date.year.getValue()) { if(month.getValue() > date.month.getValue()) { return true; } else if(month.getValue() == date.month.getValue()) { if(day.getValue() > date.day.getValue()) return true; else return false; } else return false; } else return false; } public String showDate() { return year.getValue()+"-"+month.getValue()+"-"+day.getValue() ; } public int getDaysofDates(DateUtil date) { int differ = 0; int temp1 = 0; int temp2 = 0; int[] monthly = {31,28,31,30,31,30,31,31,30,31,30,31}; for(int i = 0; i < month.getValue() - 1 ;i++) { if(year.isLeapYear()) { monthly[1] = 29; } else monthly[1] = 28; temp1 = temp1 + monthly[i] ; } monthly[1] = 28; for(int i = 0; i < date.month.getValue() - 1 ;i++) { if(date.year.isLeapYear()) { monthly[1] = 29; } else monthly[1] = 28; temp2 = temp2 + monthly[i] ; } monthly[1] = 28; differ = (temp1 + day.getValue()) - (temp2 + date.day.getValue()); int sum = 0; if(year.getValue() > date.year.getValue()) { for(int i = date.year.getValue();i < year.getValue() ;i++) { if(i % 400 == 0 || (i % 4 == 0 && i % 100 != 0)) { sum = sum + 366; } else sum = sum + 365; } sum = sum + differ; } else if(year.getValue() == date.year.getValue()) { sum = Math.abs(differ); } else { for(int i = year.getValue() ; i < date.year.getValue() ; i++) { sum = sum + 365; if(i % 400 == 0 || (i % 4 == 0 && i % 100 != 0)) sum++; } sum = sum - differ; } return sum; } } class Day { private int value; public Day() { super(); // TODO Auto-generated constructor stub } public Day(int dayValue ) { this.value = dayValue; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public void dayIncrement() { value++; } public void dayReduction() { value--; } } class Month { private int value; public Month() { super(); // TODO Auto-generated constructor stub } public Month(int monthValue) { this.value = monthValue; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public void resetMin() { value = 1; } public void resetMax() { value = 12; } public boolean validate() { if(value >= 1 && value <=12) return true; else return false; } public void monthIncrement() { value++; } public void monthReduction() { value--; } } class Year { private int value; public Year() { super(); // TODO Auto-generated constructor stub } public Year(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public boolean isLeapYear() { if(value % 400 == 0 || (value % 4 == 0 && value % 100 != 0)) return true; else return false; } public boolean validate() { if(value >= 1820 && value <= 2020) return true; else return false; } public void yearIncrement() { value++; } public void yearReduction() { value--; } }
以下为类图:

解释与心得:
依照类图创建了相应的类,利用数组存储各月的天数,在运行时通过判断是否是闰年来改变数组中的二月天数。该图中的类设计,条理清晰,赏心悦目,符合单一职责原则,属实是不可多得的好类图。相较于7-2题只有一个main类包括了所有的函数,有了类设计的代码更加简洁,条理清晰。
2.雨刷系统

第三次作业:
要求MVC模式,及单例模式,单一职责原则。
以下为Controller类的设计
package BruSys; import java.util.Scanner; public class Controller { private LeverModel lever; private DialModel dial; private BrushModel brush; private View view; private static Controller controller; public static Controller getlnstance() { if(controller == null) return new Controller(); else return controller; } private Controller() { this.lever = LeverModel.getlnstance(); this.dial = DialModel.getlnstance(); this.brush = BrushModel.getlnstance(); this.view = View.getlnstance(); } public LeverModel getLever() { return this.lever; } public void setLever(LeverModel lever) { this.lever = lever; } public DialModel getDial() { return this.dial; } public void setDial(DialModel dial) { this.dial = dial; } public BrushModel getBrush() { return this.brush; } public void setBrush(BrushModel brush) { this.brush = brush; } public void judgeSpeed() {//判断雨刷速度 int speed = 0; switch(this.lever.getPos()) { case 0:speed=0;break; case 1: switch(this.dial.getDial()){ case 1:speed =4;break; case 2:speed =6;break; case 3:speed =12;break; } break; case 2:speed =30;break; case 3:speed =60;break; } this.brush.setSpeed(speed); } public void getAction() {//获取操作信号调节相应速度和模式 Scanner in = new Scanner(System.in); char key = in.next().charAt(0); switch(key) { case'w': case'W': this.lever.upPos(); break; case's': case'S': this.lever.downPos(); break; case'.': case'>': case'。': this.dial.upDial(); break; case',': case'<': case',': this.dial.downDial(); break; } } public int getSpeed() { return this.brush.getSpeed(); } public int getGos1() { return this.lever.getPos(); } public void explain() { view.explain(); } public void updateView() {//将速度和模式数据传输给显示模块 judgeSpeed(); view.output(getSpeed(), getGos1()); } }

MVC 模式
MVC 模式代表 Model-View-Controller(模型-视图-控制器) 模式。这种模式用于应用程序的分层开发。
- Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
- View(视图) - 视图代表模型包含的数据的可视化。
- Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。

单例模式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

使用场景:
- 1、要求生产唯一序列号。
- 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
- 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。
职责原则的定义
单一职责原则(Single Responsibility Principle,SRP)又称单一功能原则,由罗伯特·C.马丁(Robert C. Martin)于《敏捷软件开发:原则、模式和实践》一书中提出的。这里的职责是指类变化的原因,单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分(There should never be more than one reason for a class to change)。
该原则提出对象不应该承担太多职责,如果一个对象承担了太多的职责,至少存在以下两个缺点:
- 一个职责的变化可能会削弱或者抑制这个类实现其他职责的能力;
- 当客户端需要该对象的某一个职责时,不得不将其他不需要的职责全都包含进来,从而造成冗余代码或代码的浪费。
单一职责原则的优点
单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。如果遵循单一职责原则将有以下优点。
- 降低类的复杂度。一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。
- 提高类的可读性。复杂性降低,自然其可读性会提高。
- 提高系统的可维护性。可读性提高,那自然更容易维护了。
- 变更引起的风险降低。变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响。
解释与心得:
在设计时符合单一职责原则并且采用了MVC及单例模式,不过在实现上有很多的不足,在语法上有些地方不规范。
三.踩坑心得:
在计算过程中经常会出现精度丢失的问题
1、Java 中 double 类型操作精度丢失问题
在使用 Java 中 double 进行运算时,经常出现精度丢失的问题,总是在一个正确的结果左右偏 0.0000**1。
我们发现,计算出来的值和我们预期结果不一致。原因在于我们的计算机是二进制的。浮点数没有办法使用二进制进行精确表示。
计算机的 CPU 表示浮点数由两个部分组成:指数和尾数,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。
浮点运算很少是精确的,只要是超过精度能表示的范围就会产生误差。往往产生误差不是因为数的大小,而是因为数的精度。因此,产生的结果接近但不等于想要的结果。尤其在使用 float 和 double 作精确运算的时候要特别小心。
总结
(1)需要精确的表示两位小数时我们需要把他们转换为 BigDecimal 对象,然后再进行运算。
(2)使用 BigDecimal(double val) 构造函数时仍会存在精度丢失问题,建议使用 BigDecimal(String val)。
其实 Java 的浮点数只能用来进行科学计算或工程计算,在大多数的商业计算中,一般采用java.math.BigDecimal 类来进行精确计算。
使用步骤:
- 用 float 或者 double 变量构建 BigDecimal 对象。通常使用 BigDecimal 的构造方法或者静态方法的 valueOf() 方法把基本类型的变量构建成 BigDecimal 对象。
- 通过调用 BigDecimal 的加,减,乘,除等相应的方法进行算术运算。
- 把 BigDecimal 对象转换成 float,double,int 等类型。
BigDecimal 类 的构造函数:
BigDecimal(int var) //创建一个具有参数所指定整数值的对象。 BigDecimal(double var) //创建一个具有参数所指定双精度值的对象。 BigDecimal(long var) //创建一个具有参数所指定长整数值的对象。 BigDecimal(String var) //创建一个具有参数所指定以字符串表示的数值的对象。
BigDecimal 类的加,减,乘,除等相应的方法:
BigDecimal add(BigDecimal augend) //加法运算 BigDecimal subtract(BigDecimal subtrahend) //减法运算 BigDecimal multiply(BigDecimal multiplicand) //乘法运算 BigDecimal divide(BigDecimal divisor) //除法运算
四:改进建议
在较多代码的程序设计中,应符合单一职责原则,切勿将所有代码都塞到一个函数内。
五:总结
在这学期的java课程我们学习到了
1.七大设计原则
2.各种设计模式
3.继承和多态
4.软件测试的方法
还有一些要改进的方面包括有关接口类的知识,及各种设计模式的学习和实践。

浙公网安备 33010602011771号