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;
	}
}

運行結果:



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章