java8:自上而下设计方法

如果让你写个程序,输入年月, 然后打印出这个月的日历?


你会怎么做呢?

 Would you immediately start coding? Begin-
ning programmers often start by trying to work out the solution to every detail. Although
details are important in the final program, concern for detail in the early stages may block the
problem-solving process. To make problem solving flow as smoothly as possible, this exam-
ple begins by using method abstraction to isolate details from design and only later imple-
ments the details.

所以我们可以采用一种自上而下的设计方式,例如这个问题需要:1)输入年月 readInput  2)打印日历PrintMonth .

而对于2) 我们又可以分为 2.1)打印title  2.2)打印主体 

而对于2.1)我们需要将输入的月份转为英文月份 

对于 2.2)打印主体的问题主要是两个 2.2.1)这个月第一天是周几? 2.2.2)这个月有多少天?

对于2.2.1) 要求这个月是周几,我们必须知道一个起始的年月日的起始,本例子用的是 1800年1月1日是周三,那么要求这个问题,需要求出这个月距离起点有多少天? totalDays;

而在计算总的天数中我们需要知道每一年是闰年还是年,求出整数年数的天数后,再加上这一年到现在的每个月的的天数(二则个问题又是跟2.2.2是一样的问题),这样总的天数就出来了。

利用这种自上而下的设计方法可得到如下图形:


然后将整体的类的抽象形式给表达出来,然后再填充具体的实现,如下:

import java.util.Scanner;
public class PrintCalendar
{
	public static void main(String [] args)
	{
		Scanner input =new Scanner(System.in);
		int year,month;
		System.out.print("Input Year:");
		year=input.nextInt();
		do
		{
			System.out.print("Input month(1-12):");
			month=input.nextInt();
		}while(month<1 || month>12);
		printTitle(year,month);
		printBody(year,month);
	}
	//PrintTitle
	public static void printTitle(int year,int month)
	{
		
		System.out.println("\t\t"+getMonthName(month)+"    "+year);
		System.out.println("-----------------------------------");
		System.out.println("  Sun  Mon  Tue  Wed  Thu  Fri  Sat");
	}
	public static String getMonthName(int month)
	{
		String monthName="";
		switch(month)
		{
			case 1: monthName="January";break;
			case 2: monthName="February";break;
			case 3: monthName="March";break;
			case 4: monthName="April";break;
			case 5: monthName="May";break;
			case 6: monthName="June";break;
			case 7: monthName="July";break;
			case 8: monthName="August";break;
			case 9: monthName="September";break;
			case 10: monthName="October";break;
			case 11: monthName="November";break;
			case 12: monthName="December";break;
		}
		return monthName;
	}
	//printBody
	public static void printBody(int year,int month)
	{
		//get the start day of week of this month
		int start=startOfMonth(year,month);
		int numOfMonth=daysOfMonth(year,month);
		for(int i=0;i<start;i++)
		{
			System.out.print("     ");
		}
		for(int i=1;i<=numOfMonth;i++)
		{
			System.out.printf("%5d",i);
			if((i+start)%7==0) System.out.println();
		}
	}	
	public static int startOfMonth(int year,int month)
	{
		int totalDays=getTotalDays(year,month);
		final int START_OF_JAN_1_1800=3;//the day of week of 1800/01/01 is Wed;
		return (totalDays+START_OF_JAN_1_1800)%7;
	}
	//get the total days from 1800/01/01
	public static int getTotalDays(int year,int month)
	{
		final int START_YEAR=1800;
		final int START_MONTH=1;
		int total=0;
		for(int i=START_YEAR;i<year;i++)
		{
			if(isLeapYear(i)) total+=366;
			else total+=365;
		}
		for(int i=1;i<month;i++)
		{
			total+=daysOfMonth(year,i);
		}
		return total;
	}
	public static boolean isLeapYear(int year)
	{
		if((year%4==0 && year%100!=0)|| year%400==0) return true;
		return false;
	}
	public static int daysOfMonth(int year,int month)
	{
		int days;
		switch(month)
		{
			case 4:
			case 6:
			case 9:
			case 11:
				days=30;break;
			case 2:
				if(isLeapYear(year)) days=29;
				else days=28;
				break;
				
			default:
				days=31; break;
		}
		return days;
	}
}

运行结果:



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值