|
|
@@ -339,6 +339,14 @@ p.setId("1002");
|
|
|
System.out.printf(p.showInfo()); // 输出:Person{id='1002', name='李四'}
|
|
|
```
|
|
|
|
|
|
+**常量命名规范**:Java 中一般使用 `final` 修饰的变量作为常量,常量名称通常 **全部大写**,单词之间用下划线 `_` 分隔。例如:
|
|
|
+
|
|
|
+```java
|
|
|
+final String SPRING = "春天"; // FinalClass.java
|
|
|
+final int MAX_STUDENT_COUNT = 100;
|
|
|
+final double PI = 3.1415926;
|
|
|
+```
|
|
|
+
|
|
|
**关键区别**:
|
|
|
|
|
|
| 变量类型 | final 的作用 | 示例 |
|
|
|
@@ -445,7 +453,147 @@ public class Test {
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 五、随堂练习要点
|
|
|
+## 五、模板方法设计模式(Template Method Pattern)
|
|
|
+
|
|
|
+### 1. 模板方法的引出
|
|
|
+
|
|
|
+**文件**:`Demo03.java`
|
|
|
+
|
|
|
+**模板方法模式**是抽象类的经典应用场景。核心思想:**父类定义算法的「骨架」(通用结构),子类实现特定的「步骤」(定制化需求)**。
|
|
|
+
|
|
|
+```
|
|
|
+Java中的设计模式:模板模式
|
|
|
+是把抽象类整体看成是一个模版,模板中不能决定的东西,抽象成方法
|
|
|
+让使用模板的类(也就是抽象类的子类)去重写抽象方法,实现定制化的需求。
|
|
|
+模板模式的优势:
|
|
|
+ 模板已经定义了通用的结构,使用者只需要关心自己需要实现的功能就可以了
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 模板类的组成
|
|
|
+
|
|
|
+**文件**:`MyOneDayTemplate.java`
|
|
|
+
|
|
|
+一般模板类分为两部分:
|
|
|
+
|
|
|
+| 组成部分 | 关键字 | 说明 |
|
|
|
+|---------|--------|------|
|
|
|
+| **模板方法** | `final` | 定义执行步骤的骨架,子类不能修改(不能重写) |
|
|
|
+| **抽象方法** | `abstract` | 需要被子类重写的方法,具体行为由子类决定 |
|
|
|
+
|
|
|
+```java
|
|
|
+package course;
|
|
|
+
|
|
|
+public abstract class MyOneDayTemplate {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 模板方法——使用 final 修饰,只能使用,不能修改
|
|
|
+ */
|
|
|
+ public final void myOneDay() {
|
|
|
+ System.out.print("《我的一天》");
|
|
|
+ System.out.print("今天我吃了");
|
|
|
+ this.eat(); // 步骤 1:吃(抽象方法,子类实现)
|
|
|
+ System.out.print("然后我又");
|
|
|
+ this.sleep(); // 步骤 2:睡(抽象方法,子类实现)
|
|
|
+ System.out.print("最后我又玩了");
|
|
|
+ this.play(); // 步骤 3:玩(抽象方法,子类实现)
|
|
|
+ System.out.print("好开心哟~");
|
|
|
+ System.out.println();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 抽象方法——由子类提供具体的实现
|
|
|
+ public abstract void eat();
|
|
|
+ public abstract void sleep();
|
|
|
+ public abstract void play();
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+> **关键点**:`myOneDay()` 用 `final` 修饰,确保子类不能篡改这个方法的结构。子类只需关注 `eat()`、`sleep()`、`play()` 三个抽象方法的具体实现。
|
|
|
+
|
|
|
+### 3. 子类实现
|
|
|
+
|
|
|
+**文件**:`ZhSanOneDay.java`、`LiSiOneDay.java`
|
|
|
+
|
|
|
+```java
|
|
|
+// 张三的一天
|
|
|
+public class ZhSanOneDay extends MyOneDayTemplate {
|
|
|
+ @Override
|
|
|
+ public void eat() {
|
|
|
+ System.out.println("饭");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void sleep() {
|
|
|
+ System.out.println("菜");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void play() {
|
|
|
+ System.out.println("小狗");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 李四的一天
|
|
|
+public class LiSiOneDay extends MyOneDayTemplate {
|
|
|
+ @Override
|
|
|
+ public void eat() {
|
|
|
+ System.out.println("饭");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void sleep() {
|
|
|
+ System.out.println("菜");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void play() {
|
|
|
+ System.out.println("小狗");
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 4. 测试类
|
|
|
+
|
|
|
+**文件**:`Test03.java`
|
|
|
+
|
|
|
+```java
|
|
|
+public class Test03 {
|
|
|
+ public static void main(String[] args) {
|
|
|
+ ZhSanOneDay zhSanOneDay = new ZhSanOneDay();
|
|
|
+ zhSanOneDay.myOneDay();
|
|
|
+
|
|
|
+ LiSiOneDay li = new LiSiOneDay();
|
|
|
+ li.myOneDay();
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**预期输出**:
|
|
|
+```
|
|
|
+《我的一天》今天我吃了饭然后我又菜最后我又玩了好开心哟~
|
|
|
+《我的一天》今天我吃了饭然后我又菜最后我又玩了好开心哟~
|
|
|
+```
|
|
|
+
|
|
|
+### 5. 模板方法模式的优势
|
|
|
+
|
|
|
+| 优势 | 说明 |
|
|
|
+|------|------|
|
|
|
+| **复用性** | 公共的流程代码写在父类的模板方法中,所有子类共用 |
|
|
|
+| **扩展性** | 新增一种「一天」只需新建子类,重写抽象方法即可 |
|
|
|
+| **规范性** | 父类通过模板方法强制规定了执行顺序和结构,子类无法改变 |
|
|
|
+| **关注分离** | 使用者只需关心自己的定制逻辑(吃什么/睡什么/玩什么),不用关注整体流程 |
|
|
|
+
|
|
|
+### 6. 模板方法 vs 普通继承 + 方法重写
|
|
|
+
|
|
|
+| 对比维度 | 普通继承 + 方法重写 | 模板方法模式 |
|
|
|
+|---------|-------------------|-------------|
|
|
|
+| **父类方法** | 普通方法,子类可选择重写或不重写 | 模板方法用 `final` 修饰,**禁止重写** |
|
|
|
+| **执行流程** | 由调用方决定调用顺序 | 父类模板方法定义固定执行顺序 |
|
|
|
+| **强制约束** | 弱——子类可以不重写 | 强——子类必须重写抽象方法 |
|
|
|
+| **设计意图** | 复用代码 | 定义算法骨架 + 强制子类实现特定步骤 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 六、随堂练习要点
|
|
|
|
|
|
**练习目标**:理解抽象类的定义和使用
|
|
|
|
|
|
@@ -455,7 +603,7 @@ public class Test {
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 六、面试常见问题
|
|
|
+## 七、面试常见问题
|
|
|
|
|
|
**Q1:抽象类能不能被实例化?**
|
|
|
> 不能。抽象类不能直接 `new` 创建对象。
|
|
|
@@ -478,9 +626,15 @@ public class Test {
|
|
|
**Q7:`final` 修饰的类有哪些常见例子?**
|
|
|
> `String` 类、`Math` 类、`Integer` 等包装类都是用 `final` 修饰的,它们不能被继承。
|
|
|
|
|
|
+**Q8:什么是模板方法设计模式?它的核心思想是什么?**
|
|
|
+> 模板方法模式(Template Method Pattern)是抽象类的经典应用场景。核心思想是:**父类定义算法的「骨架」(通用结构),子类实现特定的「步骤」(定制化需求)**。父类中的模板方法用 `final` 修饰禁止重写,抽象方法用 `abstract` 修饰强制子类实现。
|
|
|
+
|
|
|
+**Q9:模板方法模式中,模板方法为什么用 `final` 修饰?**
|
|
|
+> 为了防止子类篡改算法的执行流程。如果模板方法不被 `final` 修饰,子类可以重写它,破坏父类定义好的步骤结构,失去了「模板」的意义。
|
|
|
+
|
|
|
---
|
|
|
|
|
|
-## 七、拓展阅读
|
|
|
+## 八、拓展阅读
|
|
|
|
|
|
- [Java 抽象类(Oracle 官方文档)](https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html)
|
|
|
- 抽象类 vs 接口(Interface)的区别(将在后续课程中讲解)
|