赞
踩
01.如果接到一个任务,要求设计不同型号的悍马车
02.设计一个悍马车的抽象类(模具,车模)
public abstract class HummerModel { /* * 首先,这个模型要能够被发动起来,别管是手摇发动,还是电力发动,反正 * 是要能够发动起来,那这个实现要在实现类里了 */ public abstract void start(); //能发动,那还要能停下来,那才是真本事 public abstract void stop(); //喇叭会出声音,是滴滴叫,还是哔哔叫 public abstract void alarm(); //引擎会轰隆隆的响,不响那是假的 public abstract void engineBoom(); //那模型应该会跑吧,别管是人推的,还是电力驱动,总之要会跑 public abstract void run(); }
03.具体不同版本的悍马,这个是抽象类的具体子类
H1 型号悍马的定义如下:
public class HummerH1Model extends HummerModel { @Override public void alarm() { System.out.println("悍马H1鸣笛..."); } @Override public void engineBoom() { System.out.println("悍马H1引擎声音是这样在..."); } @Override public void start() { System.out.println("悍马H1发动..."); } @Override public void stop() { System.out.println("悍马H1停车..."); } /* * 这个方法是很有意思的,它要跑,那肯定要启动,停止了等,也就是要调其他方法 */ @Override public void run() { //先发动汽车 this.start(); //引擎开始轰鸣 this.engineBoom(); //然后就开始跑了,跑的过程中遇到一条狗挡路,就按喇叭 this.alarm(); //到达目的地就停车 this.stop(); } }
然后看悍马 H2 型号的实现:
public class HummerH2Model extends HummerModel { @Override public void alarm() { System.out.println("悍马H2鸣笛..."); } @Override public void engineBoom() { System.out.println("悍马H2引擎声音是这样在..."); } @Override public void start() { System.out.println("悍马H2发动..."); } @Override public void stop() { System.out.println("悍马H1停车..."); } /* * H2要跑,那肯定要启动,停止了等,也就是要调其他方法 */ @Override public void run() { //先发动汽车 this.start(); //引擎开始轰鸣 this.engineBoom(); //然后就开始跑了,跑的过程中遇到一条狗挡路,就按喇叭 this.alarm(); //到达目的地就停车 this.stop(); } }
然后程序写到这里,你就看到问题了,run 方法的实现应该在抽象类上(子类改写的都一样),不应该在实现类上,好,我们修改一下类图和实现:
就把 run 方法放到了抽象类中,那代码也相应的改变一下,先看 HummerModel.java:
04.修改后的抽象类
public abstract class HummerModel { /* * 首先,这个模型要能够被发动起来,别管是手摇发动,还是电力发动,反正 * 是要能够发动起来,那这个实现要在实现类里了 */ public abstract void start(); //能发动,那还要能停下来,那才是真本事 public abstract void stop(); //喇叭会出声音,是滴滴叫,还是哔哔叫 public abstract void alarm(); //引擎会轰隆隆的响,不响那是假的 public abstract void engineBoom(); //那模型应该会跑吧,别管是人退的,还是电力驱动,总之要会跑 public void run() { //先发动汽车 this.start(); //引擎开始轰鸣 this.engineBoom(); //然后就开始跑了,跑的过程中遇到一条狗挡路,就按喇叭 this.alarm(); //到达目的地就停车 this.stop(); } }
05.修改后的抽象类的子类:
public class HummerH1Model extends HummerModel { @Override public void alarm() { System.out.println("悍马H1鸣笛..."); } @Override public void engineBoom() { System.out.println("悍马H1引擎声音是这样在..."); } @Override public void start() { System.out.println("悍马H1发动..."); } @Override public void stop() { System.out.println("悍马H1停车..."); } }
public class HummerH2Model extends HummerModel { @Override public void alarm() { System.out.println("悍马H2鸣笛..."); } @Override public void engineBoom() { System.out.println("悍马H2引擎声音是这样在..."); } @Override public void start() { System.out.println("悍马H2发动..."); } @Override public void stop() { System.out.println("悍马H2停车..."); } }
06.运行程序
public class Client {
public static void main(String[] args) {
//客户开着H1型号,出去遛弯了
HummerModel h1 = new HummerH1Model();
h1.run(); //汽车跑起来了;
//客户开H2型号,出去玩耍了
HummerModel h2 = new HummerH2Model();
h2.run();
}
}
07.客户只要在 run 的过程中,听到或看都成了呀,暴露那么多的方法干啥?把抽象方法保护起来
把抽象类上的四个方法设置为 protected 访问权限,好了,既然客户不关心这几个方法,而且这四个方法都是由子类来实现的,那就设置成 protected 模式。咦~,那还有个缺陷,run 方法既然子类都不修改,那是不是可以设置成 final 类型呢?是滴是滴,类图如下:
public abstract class HummerModel { /* * 首先,这个模型要能够被发动起来,别管是手摇发动,还是电力发动,反正 * 是要能够发动起来,那这个实现要在实现类里了 */ protected abstract void start(); //能发动,那还要能停下来,那才是真本事 protected abstract void stop(); //喇叭会出声音,是滴滴叫,还是哔哔叫 protected abstract void alarm(); //引擎会轰隆隆的响,不响那是假的 protected abstract void engineBoom(); //那模型应该会跑吧,别管是人退的,还是电力驱动,总之要会跑 final public void run() { //先发动汽车 this.start(); //引擎开始轰鸣 this.engineBoom(); //然后就开始跑了,跑的过程中遇到一条狗挡路,就按喇叭 this.alarm(); //到达目的地就停车 this.stop(); } }
大家请看这个 run 方法,他定义了调用其他方法的顺序,并且子类是不能修改的,这个叫做模板方法;start、stop、alarm、engineBoom 这四个方法是子类必须实现的,而且这四个方法的修改对应了不同的类,这个叫做基本方法,基本方法又分为三种:在抽象类中实现了的基本方法叫做具体方法;在抽象类中没有实现,在子类中实现了叫做抽象方法,我们这四个基本方法都是抽象方法,由子类来实现的;还有一种叫做钩子方法,
。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。