先看例子:
类图
非常简单的实现,悍马车有两个型号,H1和H2。按照需求,只需要悍马模型,那好我 就给你悍马模型,先写个抽象类,然后两个不同型号的模型实现类,通过简单的继承就可以 实现业务要求。
先设计一个悍马汽车的抽象模型
public abstract class HummerTemplate {
protected abstract void start(); //汽车发动
protected abstract void stop(); //汽车停止
protected abstract void alarm(); //汽车鸣笛
protected abstract void engineBoom(); //汽车引擎轰隆隆
public abstract void run();//汽车跑起来了
}
这是悍马模型1的实现:
public class Hummer1 extends HummerTemplate {
@Override
protected void start() {
System.out.println("悍马汽车1号启动了");
}
@Override
protected void stop() {
System.out.println("悍马汽车1号停止了");
}
@Override
protected void alarm() {
System.out.println("悍马汽车1号鸣笛了");
}
@Override
protected void engineBoom() {
System.out.println("悍马汽车1号引擎声很性感");
}
@Override
public void run() {
this.start();
this.engineBoom();
this.alarm();
this.stop();
}
}
这是悍马模型2的实现:
public class Hummer2 extends HummerTemplate {
@Override
protected void start() {
System.out.println("悍马汽车2号启动了");
}
@Override
protected void stop() {
System.out.println("悍马汽车2号停止了");
}
@Override
protected void alarm() {
System.out.println("悍马汽车2号鸣笛了");
}
@Override
protected void engineBoom() {
System.out.println("悍马汽车2号引擎声很性感");
}
@Override
public void run() {
this.start();
this.engineBoom();
this.alarm();
this.stop();
}
}
把我们设计的两个悍马模型构造出来:
public class Main {
public static void main(String[] args) {
HummerTemplate hummer1 = new Hummer1();
hummer1.run();
System.out.println("==========================");
HummerTemplate hummer2 = new Hummer2();
hummer2.run();
}
}
输出:
悍马汽车1号启动了
悍马汽车1号引擎声很性感
悍马汽车1号鸣笛了
悍马汽车1号停止了
==========================
悍马汽车2号启动了
悍马汽车2号引擎声很性感
悍马汽车2号鸣笛了
悍马汽车2号停止了
可以发现悍马1与悍马2其实启动的过程都是一样的造成了代码冗余,那么可以把run()抽取到抽象类中作为默认实现,这样两个悍马车就能共用一个run()来启动了。
改动如下:
//悍马模型
public abstract class HummerTemplate {
protected abstract void start(); //汽车发动
protected abstract void stop(); //汽车停止
protected abstract void alarm(); //汽车鸣笛
protected abstract void engineBoom(); //汽车引擎轰隆隆
public void run(){//汽车跑起来了
this.start();
this.engineBoom();
this.alarm();
this.stop();
}
}
//悍马1
public class Hummer1 extends HummerTemplate {
@Override
protected void start() {
System.out.println("悍马汽车1号启动了");
}
@Override
protected void stop() {
System.out.println("悍马汽车1号停止了");
}
@Override
protected void alarm() {
System.out.println("悍马汽车1号鸣笛了");
}
@Override
protected void engineBoom() {
System.out.println("悍马汽车1号引擎声很性感");
}
}
//悍马2
public class Hummer2 extends HummerTemplate {
@Override
protected void start() {
System.out.println("悍马汽车2号启动了");
}
@Override
protected void stop() {
System.out.println("悍马汽车2号停止了");
}
@Override
protected void alarm() {
System.out.println("悍马汽车2号鸣笛了");
}
@Override
protected void engineBoom() {
System.out.println("悍马汽车2号引擎声很性感");
}
}
输出:
悍马汽车1号启动了
悍马汽车1号引擎声很性感
悍马汽车1号鸣笛了
悍马汽车1号停止了
==========================
悍马汽车2号启动了
悍马汽车2号引擎声很性感
悍马汽车2号鸣笛了
悍马汽车2号停止了
可以发现运行结果是一致的,但是问题出现了,如果说悍马2不需要每次启动都鸣笛,但模版类中已经定义了这样的启动流程该怎么办呢?
其实我们需要设计一个钩子函数来确定一些模版中可能有个性话定制的功能。
//悍马模型抽象类
public abstract class HummerTemplate {
protected abstract void start(); //汽车发动
protected abstract void stop(); //汽车停止
protected abstract void alarm(); //汽车鸣笛
protected abstract void engineBoom(); //汽车引擎轰隆隆
public void run(){//汽车跑起来了
this.start();
this.engineBoom();
if (isAlarm()){
//通过判断就能控制是否鸣笛
this.alarm();
}
this.stop();
}
//子类可以重写该方法,来确定是否需要一部分可变的功能(此方法就是钩子函数,具体的值由子类就可以控制)
protected boolean isAlarm(){
//默认需要鸣笛
return true;
}
}
//悍马模型1
public class Hummer1 extends HummerTemplate {
@Override
protected void start() {
System.out.println("悍马汽车1号启动了");
}
@Override
protected void stop() {
System.out.println("悍马汽车1号停止了");
}
@Override
protected void alarm() {
System.out.println("悍马汽车1号鸣笛了");
}
@Override
protected void engineBoom() {
System.out.println("悍马汽车1号引擎声很性感");
}
@Override
protected boolean isAlarm() {
//悍马1出厂设定就是需要鸣笛,想改都不给机会
return true;
}
}
//悍马模型2
public class Hummer2 extends HummerTemplate {
private boolean alarmFlag = true;
@Override
protected void start() {
System.out.println("悍马汽车2号启动了");
}
@Override
protected void stop() {
System.out.println("悍马汽车2号停止了");
}
@Override
protected void alarm() {
System.out.println("悍马汽车2号鸣笛了");
}
@Override
protected void engineBoom() {
System.out.println("悍马汽车2号引擎声很性感");
}
//悍马2升级了,把是否鸣笛选择权交给了用户,默认鸣笛,传入0则不鸣笛;
public void setAlarmFlag(int flag){
if (flag == 0){
this.alarmFlag = false;
}
}
@Override
protected boolean isAlarm() {
//这个返回值就决定了是否鸣笛,这就是钩子函数的作用
return this.alarmFlag;
}
}
//为客户定制悍马
public class Main {
public static void main(String[] args) {
Hummer1 hummer1 = new Hummer1();
hummer1.run();
System.out.println("==========================");
Hummer2 hummer2 = new Hummer2();
//客户选择了0 悍马不鸣笛
hummer2.setAlarmFlag(0);
hummer2.run();
}
}
输出:
悍马汽车1号启动了
悍马汽车1号引擎声很性感
悍马汽车1号鸣笛了
悍马汽车1号停止了
==========================
悍马汽车2号启动了
悍马汽车2号引擎声很性感
悍马汽车2号停止了