下表中左侧的简单实现将日、月和年设为实例变量,这样实例方法就可以直接返回适当的值;右侧的实现更加节省空间,仅使用了一个int变量来表示一个日期。 它将d日、m月和y年的一个日期表示为一个混合进制的整数512y+32m+d。用例分辨这两种实现的区别的一种方法可能是打破我们对日期的隐式假设:第二种实现的正确性基于日的值在0到31之间,月的值在0到15之间,年的值为正(在实际应用中,两种实现都应该检查月份的值是否在1到12之间,日的值是否在1到31之间)。这个例子的主要意思是说明我们在API中极少完整地指定对实现的要求。用例要分辨出这两种实现的区别的另种方法是性能:右侧的实现中保存数据类型的值所需的空间较少,代价是在向用例按照约定的格式提供这些值时花费的时间更多(需要进行一两次算数运算)。在实现中使用数据抽象的一个关键优势是我们可以将一种实现替换为另一种而无需改变用例的任何代码。
public class Date | |
---|---|
Date(int. month, int day,. int year) | 创建一个日期 |
int day() | 日 |
int month() | 月 |
int year() | 年 |
String toString() | 对象的字符串表示 |
public static void main(String[] args){
int m = Integer.parseInt(argst[0]);
int d= Integer.parseInt(args[1]);
int y= Integer.parseInt(args[2]);
Date date = new Date(m, d, y);
System.out.printIn(date);
}
public class Date{
private final int month;
private final int day;
private final int year;
public Date(int m,int y,int d){
month=m; day=d; year=y;
}
public int month(){
return month();
}
public int day(){
return day();
}
public int year(){
return year();
}
public String toString(){
return month()+"/"+ day()+"/"+ year();
}
}
下表的累加器API定义了一种能够为用例计算一组数据的实时平均值的抽象数据类型。它的实现很简单:它维护一个int类型的实例变量来记录已经处理过的数据值的数量,以及一个 double类型的实例变量来记录所有数据值之和,将和除以数据数量即可得到平均值。请注意该实现并没有保存数据的值——它可以用于处理大规模的数据。而一个大型系统也可以大量使用累加器。 这种性能特点很容易被忽视,所以应该在API中注明,因为种存储所有数据值的实现可能会使调用它的应用程序用光所有内存。
public class Accumulator | |
---|---|
Accumulator() | 创建一个累加器 |
void addDataValue(double val) | 添加一个新的数据值 |
double mean() | 所有数据值的平均值 |
String toString() | 对象的字符串表示 |
public class TestAccumulator{
public static void main(String[] args){
int T=Integer . parseInt(args [0]) ;
Accumulator a=new Accumulator();
for(int t=0;t<T;t++){
a.addDataValue(Random .random());
System.out.printIn(a);
}
}
}
public class Accumulator{
private double total;
private int N;
public void addDataValue(double val){
N++;
total += val;
}
public double mean(){
return total/N;
}
public String toString(){
return"Mean("+N+String. format("%7.5f", mean());
}
}