文章目录
- 一、抽象类的定义
- 二、抽象类的关键特点
- 三、抽象类的使用场景
-
- [3.1 模板方法模式](#3.1 模板方法模式)
- [3.2 工厂方法模式](#3.2 工厂方法模式)
一、抽象类的定义
如果一个类不能表示一个具体的对象,此时就可以被定义为抽象类,从语法上来讲使用abstract来修饰
抽象类(abstract class)就像一个半成品模板,它定义了一组子类必须遵循的规则(方法、属性),但自己又不完整,不能直接拿来用(无法实例化),必须由子类继承并补充完整(实现抽象方法)后才能使用。
举个生活例子:"交通工具"就是一个抽象概念,它具有行驶这个通用行为,但是你没法直接创建一个交通工具实体;而"汽车""自行车"继承了交通工具,并具体实现了行驶(汽车烧油跑,自行车蹬着邹),这就是抽象类的核心思想。
二、抽象类的关键特点
-
不能实例化:无法直接创建抽象类的对象(比如new 交通工具()是错误的)。
-
包含抽象方法:抽象方法只有方法声明(定义要做什么),没有方法体(没说"怎么做"),必须由子类重写实现,前面需要加关键字abstract表示抽象方法,否则就不是抽象方法,必须存在方体。
-
可以包含普通方法/属性:抽象类也能有已实现的普通方法、成员变量,供子类直接使用(复用代码)。
-
子类必须实现所有抽象方法:除非子类也是抽象类,否则必须重写父类所有抽象方法,否则编译报错。
-
如果一个类当中存在抽象方法,那么这个类一定是抽象类。如果一个类是抽象类,这个类当中可以没有抽象方法
-
定义抽象类
java
//用abstract关键字声明抽象类
public abstract class Vehicle {
//普通属性:所有交通工具都有名称
protected String name;
//普通方法:已实现的通用逻辑,子类可直接用
public void setName(String name) {
this.name = name;
}
//抽象方法:只有声明,没有方法体(用;结尾)
//定义了行驶这个规则,但没说具体怎么行驶
public abstract void run();
}
- 子类继承并实现抽象方法
java
//汽车类继承抽象类Vehicle
public class Car extends Vehicle{
//必须实现父类的抽象方法run()
@Override
public void run() {
System.out.println(name + "燃油,四轮行驶");
}
}
//自行车类继承抽象类Vehicle
public class Cycle extends Vehicle {
//必须实现父类的抽象方法run()
@Override
public void run() {
System.out.println(name + "人力,两轮驱动");
}
}
如果不实现父类的抽象方法则会发生编译错误:

使用子类(抽象类无法进行实例化)

java
public class Test {
public static void main(String[] args) {
//错误:抽象类不能实例化
//Vehicle vehicle = new Vehicle();
//正确:实例化子类
Vehicle car = new Car();
car.setName("特斯拉");
car.run();
Vehicle bicycle = new Cycle();
bicycle.setName("自行车");
bicycle.run();
}
}
三、抽象类的使用场景
- 代码复用 + 规范约束:当多个类共同的属性 / 方法(可抽成抽象类的普通成员),但核心行为实现不同(抽成抽象方法)时,用抽象类统一规范,避免子类 "各自为政"。
- 定义模板方法:抽象类实现核心流程(模板方法),把可变的步骤留给子类实现(比如 "制作饮品" 的模板:烧水→冲泡→装杯,其中 "冲泡" 是抽象方法,咖啡 / 茶子类分别实现)。
3.1 模板方法模式
这是抽象类最核心、最典型的应用场景,没有之一。
核心思想:抽象类定义一个算法的骨架(模板),把算法中可变的步骤延迟到子类实现,固定的通用步骤则在抽象类中实现,保证算法结构不变,同时能让子类灵活定制部分步骤。
代码示例(冲饮品场景)
java
// 抽象类:定义冲饮品的通用模板
public abstract class Beverage {
// 模板方法:固定算法流程(不能被子类修改,用final保护)
public final void prepareBeverage() {
boilWater(); // 固定步骤1:烧水
brew(); // 可变步骤:冲泡(子类实现)
pourInCup(); // 固定步骤2:装杯
addCondiments(); // 可变步骤:加调料(子类实现)
}
// 固定方法:所有饮品都要烧水
private void boilWater() {
System.out.println("烧开水(100℃)");
}
// 固定方法:所有饮品都要装杯
private void pourInCup() {
System.out.println("倒入杯中");
}
// 抽象方法:冲泡(咖啡/茶的实现不同)
protected abstract void brew();
// 抽象方法:加调料(咖啡加糖奶,茶加柠檬/蜂蜜)
protected abstract void addCondiments();
}
// 咖啡子类:实现抽象方法
public class Coffee extends Beverage {
@Override
protected void brew() {
System.out.println("冲泡咖啡粉");
}
@Override
protected void addCondiments() {
System.out.println("加方糖和牛奶");
}
}
// 茶子类:实现抽象方法
public class Tea extends Beverage {
@Override
protected void brew() {
System.out.println("冲泡茶叶");
}
@Override
protected void addCondiments() {
System.out.println("加柠檬片");
}
}
// 测试
public class TestTemplate {
public static void main(String[] args) {
Beverage coffee = new Coffee();
System.out.println("制作咖啡:");
coffee.prepareBeverage();
System.out.println("\n制作茶:");
Beverage tea = new Tea();
tea.prepareBeverage();
}
}
抽象类的作用
- 封装不变部分(烧水、装杯),避免子类重复编写;
- 声明可变部分(冲泡、加调料)为抽象方法,强制子类实现;
- 用final保护模板方法,防止子类篡改算法整体流程。
3.2 工厂方法模式
属于创建型模式,抽象类在这里扮演"抽象工厂"的角色,定义创建产品的接口,具体创建逻辑交给子类实现
核心思想:抽象工厂类声明一个创建产品的抽象方法,每个具体工厂子类负责创建对应的具体产品,解耦"产品创建"和"产品使用"。
》简单的用话来说就是:工厂=生产东西的地方;工厂方法=一个专门用来创建对象的方法。把创建对象的代码单独抽出来交给工厂做,你只管使用,不管怎么创建,也就是你要什么,跟工厂说,工厂给你造好,你直接用。就比如奶茶店:你去买奶茶,你不需要知道奶茶怎么煮,加多少奶加多少珍珠,你只需要和店员说我要珍珠奶茶,店员直接给你一杯做好的奶茶。这就是工厂方法模式,奶茶=对象,店员=工厂,你点单=调用工厂方法,你拿到奶茶=获取对象。
代码示例
java
// 第一步:定义产品抽象类(所有日志记录器的通用规范)
public abstract class Logger {
// 抽象方法:记录日志
public abstract void log(String message);
}
// 具体产品1:文件日志记录器
public class FileLogger extends Logger {
@Override
public void log(String message) {
System.out.println("写入文件:" + message);
}
}
// 具体产品2:控制台日志记录器
public class ConsoleLogger extends Logger {
@Override
public void log(String message) {
System.out.println("打印到控制台:" + message);
}
}
// 第二步:定义抽象工厂类(创建日志记录器的工厂模板)
public abstract class LoggerFactory {
// 抽象工厂方法:创建日志记录器(子类决定创建哪种)
public abstract Logger createLogger();
// 通用方法:获取日志器并记录(复用逻辑)
public void recordLog(String message) {
Logger logger = createLogger();
logger.log(message);
}
}
// 具体工厂1:创建文件日志器
public class FileLoggerFactory extends LoggerFactory {
@Override
public Logger createLogger() {
// 可添加文件日志器的初始化逻辑(如创建文件、权限检查)
return new FileLogger();
}
}
// 具体工厂2:创建控制台日志器
public class ConsoleLoggerFactory extends LoggerFactory {
@Override
public Logger createLogger() {
return new ConsoleLogger();
}
}
// 测试
public class TestFactory {
public static void main(String[] args) {
LoggerFactory factory1 = new FileLoggerFactory();
factory1.recordLog("用户登录成功"); // 输出:写入文件:用户登录成功
LoggerFactory factory2 = new ConsoleLoggerFactory();
factory2.recordLog("系统启动失败"); // 输出:打印到控制台:系统启动失败
}
}
抽象类的作用
- Logger(产品抽象类):规范所有日志记录器的核心行为(log方法);
- LoggerFactory(工厂抽象类):定义创建产品的接口(createLogger),同时封装通用的日志记录逻辑(recordLog),实现代码复用。