(27)模块方法模式(理解抽象、继承和final)
需求:获取一段程序的运行时间
原理:获取程序开始和结束的时间并相减即可
获取时间:java.lang.System类中的currentTimeMills()静态方法,返回值为long类型的当前时间与协调世界时 1970 年 1 月 1 日午夜之间的时间差(以毫秒为单位测量)。
第一想法:将待测时间代码块放在开始时间和结束时间之间
public class getTime {
public void getTime() {
long start=System.currentTimeMillis();
for(int i=0;i<1000;i++)//代码块
{
System.out.print(i);
}
long end=System.currentTimeMillis();
System.out.println();
System.out.println("毫秒:"+(end-start));
}
}
public class getTimeDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
getTime gt=new getTime();
gt.getTime();
}
}
这种思考方式把待测时间代码块放在开始时间和结束时间之间,如果要计算代码运行时间,就得对代码改动,而且在代码里面改更难。这时,可以通过继承,进行方法复写,具体实现如下:
public class getTime {
public void getTime() {
long start=System.currentTimeMillis();
for(int i=0;i<1000;i++)//代码块
{
System.out.print(i);
}
long end=System.currentTimeMillis();
System.out.println();
System.out.println("毫秒:"+(end-start));
}
}
public class subgetTime extends getTime{
public void getime(){//复写
long start=System.currentTimeMillis();
for(int i=0;i<10000;i++)//代码块
{
System.out.print(i);
}
long end=System.currentTimeMillis();
System.out.println();
System.out.println("毫秒:"+(end-start));
}
}
这样虽然能够完成,但是代码重复率太高,只是代码块发生了变化,其他都没变。既然是代码块变化,我们可以把代码块单独放置,然后让getTime()方法调用代码块方法。还需通过继承,具体如下:
public class getTime {
public void getTime() {
long start=System.currentTimeMillis();
runCode();
System.out.println("毫秒:"+(end-start));
}
public void runCode(){
for(int i=0;i<1000;i++)//代码块
{
System.out.print(i);
}
}}
public class subgetTime extends getTime{
public void runCode(){//复写
for(int i=0;i<10000;i++)//代码块
{
System.out.print(i);
}
}
}
public class getTimeDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
subetTime gt=new subgetTime();
gt.getTime();
}
}
其实父类中的runCode()方法内的方法体,写着也多余,因为代码的不确定性
public class getTime {
public void getTime() {
long start=System.currentTimeMillis();
runCode();
System.out.println("毫秒:"+(end-start));
}
public void runCode(){
}
}
public class subgetTime extends getTime{
public void runCode(){//复写
for(int i=0;i<10000;i++)//代码块
{
System.out.print(i);
}
}
}
public class getTimeDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
subetTime gt=new subgetTime();
gt.getTime();
}
}
这个时候,runCode()方法,在getTime类中显得多余了。这时想到抽象方法,抽象类。
public abstract class getTime {
public void getTime() {
long start=System.currentTimeMillis();
runCode();
System.out.println("毫秒:"+(end-start));
}
public abstract void runCode();
}
public class subgetTime extends getTime{
public void runCode(){//通过继承,对抽象类中的抽象方法复写
for(int i=0;i<10000;i++)//代码块
{
System.out.print(i);
}
}
}
public class getTimeDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
subetTime gt=new subgetTime();
gt.getTime();
}
}
这样,就优化了代码。重=从上面的代码可以看出,getTime()方法,就是获取代码运行时间的代码,不应该再改变(不能设为私有,私有只在类内可以使用,类外继承不可见),所以将这个方法改为final,不允许继承修改此代码
public abstract class getTime {
public final void getTime() {
long start=System.currentTimeMillis();
runCode();
System.out.println("毫秒:"+(end-start));
}
public abstract void runCode();
}
public class subgetTime extends getTime{
public void runCode(){//通过继承,对抽象类中的抽象方法复写
for(int i=0;i<10000;i++)//代码块
{
System.out.print(i);
}
}
}
public class getTimeDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
subetTime gt=new subgetTime();
gt.getTime();
}
}
当代码优化后,就可以解决这类问题。
这种方式,模板方法设计模式。
什么事模板式方法呢?
在定义功能时,功能的一部分是确定的,但是有一部分是不确定的,而确定的部分在使用不确定的部分。
那么这时就将不确定的部分暴露出来,由该类的子类去完成。但不一定用抽象,有些含默认的实现。