1、接口
用于描述类具体有什么功能,但是不给出具体实现,当某个类需要使用接口时,再去实现接口中的方法。
特点:
- 使用关键字interface定义接口。
- 不能被实例化new,可以被实现,关键字implements。
- 一个类可以实现一个或多个接口;接口可以继承一个或多个接口,实现接口的继承层次结构。
- 不可以有构造器。
- 方法默认为抽象方法没有具体实现,修饰符默认为public或省略,类必须实现接口中所有声明的方法,JDK8中引入接口默认方法。
- 常量默认为public static final 数据类型 常量名 = 值,即常量值不可修改。
- 主要用于指定规范,提倡使用面向接扣编程。
2、抽象类
当一个类中给出的信息不够全面或者无法确定其行为,给出的信息不足以描绘出一个具体对象,这往往我们称为抽象类。
特点:
- 使用关键字abstract声明抽象类。
- 不能被实例化new,可以被继承,关键字extends。
- 一个类只能继承一个抽象类。
- 可以有构造器,子类实例化时调用父类的构造方法。
- 可以包含抽象方法和普通方法,子类必须实现抽象类中所有抽象方法除非子类也是抽象类。
- 可以包含成员常量和变量,可以被子类继承使用。
- 主要目的为了复用代码,经典的就是模板方法模式。
模板方法模式
是一种行为设计模式,主要用于复用代码。主要角色:
模板方法:定义了一套流程步骤骨架,按某种顺序调用其包含的基本方法。
基本方法:是流程的某些步骤的具体实现,包含类型:
- 抽象方法:抽象类中声明,有具体子类实现。
- 具体方法:在抽象类中已经实现,在具体类中可以继承或重写它。
- 钩子方法:在抽象类中已经实现,包含用于判断的逻辑方法和需要子类重写的空方法两种。
public abstract class AbstractCook {
//模板方法
public final void doCook(){
openFire();
cooking();
if(isTasteMethod()){
taste();
}
closeFire();
}
//钩子方法
public boolean isTasteMethod() {
return false;
}
//空方法
protected void taste(){
}
//抽象方法
protected abstract void cooking();
//具体方法
protected void openFire() {
System.out.println("点火做菜!");
}
protected void closeFire() {
System.out.println("关火出锅!");
}
}
public class CrayFish extends AbstractCook {
//重写抽象方法
@Override
protected void cooking() {
System.out.println("一份烤鱼!");
}
//重写钩子方法
@Override
public boolean isTasteMethod() {
return true;
}
//重写空方法
@Override
protected void taste() {
System.out.println("多放辣,变态辣味!");
}
}
public class BeefNoodles extends AbstractCook {
//重写抽象方法
@Override
protected void cooking() {
System.out.println("一份牛肉面!");
}
}
public class TemplateMethodTest {
public static void main(String[] args) {
AbstractCook fish = new Crayfish();
fish.doCook();
//输出结果:
//点火做菜!
//一份烤鱼!
//多放辣,变态辣味!
//关火出锅!
AbstractCook beef = new BeefNoodles ();
beef.doCook();
//输出结果:
//点火做菜!
//一份牛肉面!
//关火出锅!
}
}