阶段总结

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)。

该原则提出对象不应该承担太多职责,如果一个对象承担了太多的职责,至少存在以下两个缺点:

  1. 一个职责的变化可能会削弱或者抑制这个类实现其他职责的能力;
  2. 当客户端需要该对象的某一个职责时,不得不将其他不需要的职责全都包含进来,从而造成冗余代码或代码的浪费。

单一职责原则的优点

单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。如果遵循单一职责原则将有以下优点。

    • 降低类的复杂度。一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。
    • 提高类的可读性。复杂性降低,自然其可读性会提高。
    • 提高系统的可维护性。可读性提高,那自然更容易维护了。
    • 变更引起的风险降低。变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响。

 

解释与心得:

在设计时符合单一职责原则并且采用了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 类来进行精确计算。

使用步骤:
  1. 用 float 或者 double 变量构建 BigDecimal 对象。通常使用 BigDecimal 的构造方法或者静态方法的 valueOf() 方法把基本类型的变量构建成 BigDecimal 对象。
  2. 通过调用 BigDecimal 的加,减,乘,除等相应的方法进行算术运算。
  3. 把 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.软件测试的方法
还有一些要改进的方面包括有关接口类的知识,及各种设计模式的学习和实践。

posted @ 2022-04-03 19:13  内卷达人  阅读(67)  评论(0)    收藏  举报