背景
本文是Java修仙系列之设计模式。若想详细学习修仙系列,请点击首篇博文,开始学习。
设计模式
设计模式分为创建型、结构型和行为型三大类。
核心是:用固定模型解决重复出现的代码问题,降低耦合、提高复用,让代码更易维护。
一、创建型模式
核心:解决“对象创建”的问题,隐藏创建细节,解耦创建与使用,对应现实中“工厂造东西”的逻辑。
1. 单例模式
一、核心模型
现实模型:世界上只有一个太阳,所有人都共用这一个太阳,没有第二个;类比代码中,一个类只有一个实例,全局都能访问。
二、原理描述
保证一个类仅存在一个实例,并提供全局唯一访问点;避免多次实例化造成的资源浪费、状态混乱(比如连接池、全局配置类)。
三、核心特点
- 私有构造器:禁止外部直接new实例
- 全局唯一实例:类内部自己创建
- 线程安全:双重检查锁+volatile保证多线程安全
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
public class Singleton {
// volatile:保证多线程下实例的可见性,防止指令重排(避免拿到未初始化的实例)
private static volatile Singleton instance;
// 1. 私有构造函数:禁止外部直接new(相当于“太阳不能被人造”)
private Singleton() {}
// 2. 全局访问方法:唯一获取实例的入口
public static Singleton getInstance() {
// 第一次检查:避免不必要的同步(大部分情况实例已存在,直接返回)
if (instance == null) {
// 同步锁:保证多线程下只有一个线程能进入创建实例
synchronized (Singleton.class) {
// 第二次检查:防止多个线程同时进入同步块,重复创建实例
if (instance == null) {
instance = new Singleton(); // 唯一一次创建实例(造太阳)
}
}
}
return instance; // 全局共用同一个实例
}
// 示例方法:模拟太阳的功能(比如“发光”)
public void showMessage() {
System.out.println("Hello, I'm a Singleton instance!(我是唯一的实例)");
}
// 测试:无论怎么获取,都是同一个实例
public static void main(String[] args) {
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
System.out.println(singleton1 == singleton2); // true(证明只有一个实例)
singleton1.showMessage();
}
}
|
2. 工厂方法模式
一、核心模型
现实模型:手机工厂 → 抽象工厂(手机工厂)定义“造手机”的接口,具体工厂(华为工厂、苹果工厂)分别造华为手机、苹果手机;你要华为就找华为工厂,要苹果就找苹果工厂,不用自己造。
核心对应:抽象工厂=手机工厂(定义造手机接口),具体工厂=华为/苹果工厂(实现造手机),产品=华为/苹果手机(具体造出来的东西)。
二、原理描述
定义一个创建对象的接口(抽象工厂),但由子类(具体工厂)决定实例化哪个产品类;延迟实例化到子类,解耦“产品创建”和“产品使用”,新增产品只需加新工厂,不用改老代码。
三、核心特点
- 一个工厂造一种产品(华为工厂只造华为手机)
- 抽象工厂定义规范,具体工厂实现细节
- 新增产品 → 新增具体产品+具体工厂,符合“开闭原则”
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
// 1. 产品接口:定义“手机”的通用功能(所有手机都能打电话)
interface Phone {
void makeCall(); // 手机的核心功能:打电话
}
// 2. 具体产品A:华为手机(实现手机接口)
class HuaweiPhone implements Phone {
@Override
public void makeCall() {
System.out.println("用华为手机打电话");
}
}
// 2. 具体产品B:苹果手机(实现手机接口)
class IPhone implements Phone {
@Override
public void makeCall() {
System.out.println("用苹果手机打电话");
}
}
// 3. 抽象工厂:手机工厂(定义“造手机”的接口,不具体造)
abstract class PhoneFactory {
// 工厂方法:造手机(由子类决定造哪种手机)
public abstract Phone createPhone();
// 业务方法:使用手机(不用管手机是谁造的,拿到就能用)
public void usePhone() {
Phone phone = createPhone(); // 工厂造手机
phone.makeCall(); // 使用手机
}
}
// 4. 具体工厂A:华为工厂(造华为手机)
class HuaweiFactory extends PhoneFactory {
@Override
public Phone createPhone() {
return new HuaweiPhone(); // 华为工厂只造华为手机
}
}
// 4. 具体工厂B:苹果工厂(造苹果手机)
class IPhoneFactory extends PhoneFactory {
@Override
public Phone createPhone() {
return new IPhone(); // 苹果工厂只造苹果手机
}
}
// 测试:要哪种手机,找对应的工厂
public class FactoryMethodDemo {
public static void main(String[] args) {
// 想要华为手机 → 找华为工厂
PhoneFactory huaweiFactory = new HuaweiFactory();
huaweiFactory.usePhone(); // 输出 "用华为手机打电话"
// 想要苹果手机 → 找苹果工厂
PhoneFactory iPhoneFactory = new IPhoneFactory();
iPhoneFactory.usePhone(); // 输出 "用苹果手机打电话"
}
}
|
3. 抽象工厂模式
一、核心模型
现实模型:家居品牌工厂 → 抽象工厂(家居工厂)定义“造椅子、造沙发”的接口(一套家居),具体工厂(现代家居工厂、欧式家居工厂)分别造“现代椅子+现代沙发”“欧式椅子+欧式沙发”;你要现代风格,就找现代工厂,一次性拿到一套配套的家居,不用分别找椅子厂、沙发厂。
核心对应:抽象工厂=家居工厂(定义造一套产品的接口),具体工厂=现代/欧式家居工厂(造一套配套产品),产品族=椅子+沙发(配套的一系列产品)。
二、原理描述
提供一个创建一系列相关/相互依赖对象(产品族)的接口,无需指定具体类;用于造“配套产品”,保证产品间能协同工作,新增产品族只需加新工厂。
关键区别(和工厂方法):工厂方法造“单一产品”,抽象工厂造“一套配套产品”。
三、核心特点
- 一个工厂造一套产品(现代工厂造现代椅子+现代沙发)
- 产品族内的产品相互配套,避免搭配混乱
- 新增产品族 → 新增具体工厂,新增单个产品需修改抽象工厂(这点是缺点)
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
// 1. 产品族:椅子和沙发(配套使用,属于同一套家居)
// 椅子接口(所有椅子都能坐)
interface Chair {
void sitOn();
}
// 沙发接口(所有沙发都能躺)
interface Sofa {
void lieOn();
}
// 2. 具体产品:现代风格(一套)
class ModernChair implements Chair {
@Override
public void sitOn() {
System.out.println("坐现代风格椅子");
}
}
class ModernSofa implements Sofa {
@Override
public void lieOn() {
System.out.println("躺现代风格沙发");
}
}
// 2. 具体产品:欧式风格(一套)
class EuropeanChair implements Chair {
@Override
public void sitOn() {
System.out.println("坐欧式风格椅子");
}
}
class EuropeanSofa implements Sofa {
@Override
public void lieOn() {
System.out.println("躺欧式风格沙发");
}
}
// 3. 抽象工厂:家居工厂(定义造“一套家居”的接口:造椅子+造沙发)
interface FurnitureFactory {
Chair createChair(); // 造椅子
Sofa createSofa(); // 造沙发(和椅子配套)
}
// 4. 具体工厂A:现代家居工厂(造现代风格一套家居)
class ModernFurnitureFactory implements FurnitureFactory {
@Override
public Chair createChair() {
return new ModernChair(); // 现代椅子
}
@Override
public Sofa createSofa() {
return new ModernSofa(); // 现代沙发(和椅子配套)
}
}
// 4. 具体工厂B:欧式家居工厂(造欧式风格一套家居)
class EuropeanFurnitureFactory implements FurnitureFactory {
@Override
public Chair createChair() {
return new EuropeanChair(); // 欧式椅子
}
@Override
public Sofa createSofa() {
return new EuropeanSofa(); // 欧式沙发(和椅子配套)
}
}
// 测试:要哪种风格,找对应的工厂,一次性拿到一套配套家居
public class AbstractFactoryDemo {
public static void main(String[] args) {
// 想要现代风格家居 → 找现代工厂
FurnitureFactory modernFactory = new ModernFurnitureFactory();
Chair modernChair = modernFactory.createChair();
Sofa modernSofa = modernFactory.createSofa();
modernChair.sitOn(); // 坐现代椅子
modernSofa.lieOn(); // 躺现代沙发(配套)
// 想要欧式风格家居 → 找欧式工厂
FurnitureFactory europeanFactory = new EuropeanFurnitureFactory();
Chair europeanChair = europeanFactory.createChair();
Sofa europeanSofa = europeanFactory.createSofa();
europeanChair.sitOn(); // 坐欧式椅子
europeanSofa.lieOn(); // 躺欧式沙发(配套)
}
}
|
补充:工厂方法 vs 抽象工厂(快速区分,加深记忆)
| 模式 |
核心模型 |
造什么 |
一句话记住 |
| 工厂方法 |
手机工厂(造单一产品) |
一种产品 |
一个工厂造一种东西 |
| 抽象工厂 |
家居工厂(造配套产品) |
一套产品(产品族) |
一个工厂造一套东西 |
4. 建造者模式
一、核心模型
现实模型:组装电脑
CPU、内存、硬盘都是配件,一步一步装进去,最后组装成一台完整电脑。
核心:复杂对象分步骤创建,灵活搭配配置。
二、原理描述
将复杂对象的创建与使用分离,通过一步步设置属性,最后构建出对象;
不用写冗长构造方法,代码更清晰、更灵活。
三、核心特点
- 一步一步创建复杂对象
- 链式调用,优雅直观
- 构造方法私有,必须通过Builder创建
- 适合参数多、组合灵活的对象
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
// 产品:电脑(复杂对象,很多配件)
class Computer {
private String cpu;
private String memory;
private String storage;
// 私有构造:外部不能直接new
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.memory = builder.memory;
this.storage = builder.storage;
}
// 建造者:专门负责一步一步创建Computer
public static class Builder {
private String cpu;
private String memory;
private String storage;
// 链式设置CPU
public Builder setCpu(String cpu) {
this.cpu = cpu;
return this;
}
// 链式设置内存
public Builder setMemory(String memory) {
this.memory = memory;
return this;
}
// 链式设置硬盘
public Builder setStorage(String storage) {
this.storage = storage;
return this;
}
// 构建:最终造出完整Computer对象
public Computer build() {
return new Computer(this);
}
}
// 展示配置
public void showSpecifications() {
System.out.println("CPU: " + cpu + ", Memory: " + memory + ", Storage: " + storage);
}
}
// 测试
public class BuilderDemo {
public static void main(String[] args) {
// 链式创建:一步一步装配件
Computer computer = new Computer.Builder()
.setCpu("Intel i7")
.setMemory("16GB")
.setStorage("512GB SSD")
.build(); // 最终建造完成
computer.showSpecifications();
}
}
|
5. 原型模式
一、核心模型
现实模型:复印机
有一个原件,直接复印一份新的,不用从头重新制作。
核心:快速复制对象,不通过new创建。
二、原理描述
通过拷贝/克隆现有对象来创建新对象,
避免复杂对象重复创建的开销,提升效率。
三、核心特点
- 基于拷贝创建对象,比直接new更快
- 隐藏对象创建细节
- 适合创建成本高、结构复杂的对象
- Java 依靠 clone() 实现
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
// 原型接口:定义克隆能力
interface Prototype extends Cloneable {
Prototype clone();
}
// 具体原型:要被复制的对象
class ConcretePrototype implements Prototype {
private String data;
// 构造:创建原始对象
public ConcretePrototype(String data) {
this.data = data;
}
// 克隆:复制一个一模一样的新对象
@Override
public Prototype clone() {
return new ConcretePrototype(this.data);
}
// 展示数据
public void showData() {
System.out.println("Data: " + data);
}
}
// 测试
public class PrototypeDemo {
public static void main(String[] args) {
// 1. 创建一个原件
ConcretePrototype original = new ConcretePrototype("Original Data");
// 2. 直接克隆(复印)一个新对象
ConcretePrototype copy = (ConcretePrototype) original.clone();
// 两个对象数据一样,但不是同一个
original.showData();
copy.showData();
}
}
|
二、结构型模式
1. 适配器模式
一、核心模型
现实模型:电源转换插头.
中国扁头电器 不能直接插 欧洲圆孔插座;
通过转换适配器做中间适配,把原有接口转换成目标接口,让原本不兼容的两者正常工作。
核心对应:
- 原有类:中国电器(已有功能、接口不匹配)
- 目标接口:欧洲插座(系统期望的统一接口)
- 适配器:转换插头(做包装、转接、兼容适配)
二、原理描述
将原有不兼容的类,通过适配器包装转换为目标统一接口;
不用修改原有代码,就能让接口不匹配的类协同工作,解决接口兼容问题。
三、核心特点
- 不改动原有业务代码,通过中间层做适配
- 兼容老系统、第三方接口、不同规格接口
- 实现原有类和目标接口解耦
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
// 目标接口,客户所期待的接口
interface Target {
void request();
}
// 需要适配的原有类,方法接口不匹配
class Adaptee {
public void specificRequest() {
System.out.println("Called specificRequest()");
}
}
// 适配器:包装原有类,实现目标接口做转接
class Adapter implements Target {
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
// 适配转发:调用原有类方法
adaptee.specificRequest();
}
}
// 测试
public class AdapterDemo {
public static void main(String[] args) {
Adaptee adaptee = new Adaptee();
Target target = new Adapter(adaptee);
target.request();
}
}
|
插座场景版代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
// 中国电器自有接口
interface ChineseElectricalDevice {
void chargeWithChinesePlug();
}
// 具体中国电器
class ChinesePhone implements ChineseElectricalDevice {
@Override
public void chargeWithChinesePlug() {
System.out.println("中国手机使用中国扁平插头充电");
}
}
// 欧洲插座目标接口
interface EuropeanSocket {
void chargeWithEuropeanPlug();
}
// 适配器:转接兼容
class PlugAdapter implements EuropeanSocket {
private ChineseElectricalDevice device;
public PlugAdapter(ChineseElectricalDevice device) {
this.device = device;
}
@Override
public void chargeWithEuropeanPlug() {
// 适配转发
device.chargeWithChinesePlug();
}
}
// 客户端测试
public class AdapterPatternExample {
public static void main(String[] args) {
ChinesePhone phone = new ChinesePhone();
PlugAdapter adapter = new PlugAdapter(phone);
adapter.chargeWithEuropeanPlug();
}
}
|
2. 桥接模式
一、核心模型
现实模型:手机 + 各类软件
手机有不同品牌(苹果/安卓),软件有不同类型(游戏/音乐);
把抽象维度(手机) 和实现维度(软件) 拆分开,用组合关联代替继承,两边可以各自独立扩展、互不影响。
核心对应:
- 抽象层:手机(整体维度)
- 实现层:软件(功能维度)
- 桥接:通过组合把两层关联,做桥梁衔接
二、原理描述
把抽象部分与实现部分分离,让两者可以独立变化扩展;
不使用多层继承膨胀,改用组合依赖关联,降低耦合,灵活切换实现。
三、核心特点
- 拆分两大变化维度,各自独立迭代
- 用组合代替继承,避免类爆炸
- 抽象和实现可动态绑定、灵活替换
四、Java 实现
1
2
3
4
5
6
7
8
9
10
|
【接口 DrawAPI】
↓ 实现
RedCircle GreenCircle
【抽象类 Shape】
↓ 继承
Circle
Shape 内部持有 DrawAPI 引用 ← 桥接
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
// 实现层接口:绘制能力
interface DrawAPI {
void drawCircle(int radius, int x, int y);
}
// 具体实现1
class RedCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle [Color: Red, Radius: " + radius + ", x: " + x + ", y:" + y + "]");
}
}
// 具体实现2
class GreenCircle implements DrawAPI {
@Override
public void drawCircle(int radius, int x, int y) {
System.out.println("Drawing Circle [Color: Green, Radius: " + radius + ", x: " + x + ", y:" + y + "]");
}
}
// 抽象层:形状,组合持有实现层引用
abstract class Shape {
protected DrawAPI drawAPI; // 这就是桥!
protected Shape(DrawAPI drawAPI) {
this.drawAPI = drawAPI;
}
public abstract void draw();
}
// 扩充抽象类
class Circle extends Shape {
private int x, y, radius;
public Circle(int x, int y, int radius, DrawAPI drawAPI) {
super(drawAPI); // super 构造只负责赋值,不负责创建
this.x = x;
this.y = y;
this.radius = radius;
}
@Override
public void draw() {
// 委托给实现层执行
drawAPI.drawCircle(radius, x, y);
}
}
// 测试
public class BridgeDemo {
public static void main(String[] args) {
Shape redCircle = new Circle(100, 100, 10, new RedCircle());
Shape greenCircle = new Circle(200, 200, 20, new GreenCircle());
redCircle.draw();
greenCircle.draw();
}
}
|
手机软件场景版代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
// 实现层抽象:软件
abstract class Software {
public abstract void run();
}
// 具体实现:游戏软件
class GameSoftware extends Software {
@Override
public void run() {
System.out.println("运行游戏软件");
}
}
// 具体实现:音乐软件
class MusicPlayerSoftware extends Software {
@Override
public void run() {
System.out.println("运行音乐播放器软件");
}
}
// 抽象层:手机,组合持有软件引用
abstract class Phone {
protected Software software;
public Phone(Software software) {
this.software = software;
}
public abstract void openSoftware();
}
// 扩充抽象:苹果手机
class ApplePhone extends Phone {
public ApplePhone(Software software) {
super(software);
}
@Override
public void openSoftware() {
System.out.println("苹果手机");
software.run();
}
}
// 扩充抽象:安卓手机
class AndroidPhone extends Phone {
public AndroidPhone(Software software) {
super(software);
}
@Override
public void openSoftware() {
System.out.println("安卓手机");
software.run();
}
}
// 客户端测试
public class BridgePatternExample {
public static void main(String[] args) {
Software gameSoftware = new GameSoftware();
Software musicPlayerSoftware = new MusicPlayerSoftware();
Phone appleGamePhone = new ApplePhone(gameSoftware);
appleGamePhone.openSoftware();
Phone androidMusicPhone = new AndroidPhone(musicPlayerSoftware);
androidMusicPhone.openSoftware();
}
}
|
3. 组合模式
一、核心模型
现实模型:电脑文件系统
根文件夹、子文件夹、文件形成树形结构;
文件夹(容器)可以包含文件和子文件夹,文件(叶子)是最小单元;
客户端统一对待单个叶子对象 和 容器组合对象,不用区分处理。
核心对应:
- 抽象组件:文件/文件夹统一规范
- 叶子节点:普通文件(无下级)
- 容器节点:文件夹(可以包含子组件)
二、原理描述
将对象组织成树形层级结构,统一定义单个对象和组合对象的行为;
客户端以统一方式处理叶子和容器,不用感知内部层级差异,整体和部分一致对待。
三、核心特点
- 树形结构收纳整体与部分
- 叶子、容器统一接口,调用无感知
- 方便层级遍历、递归处理(目录、菜单、组织架构)
四、Java 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
import java.util.ArrayList;
import java.util.List;
// 统一组件接口
interface Component {
void show();
}
// 叶子节点:最小单元
class Leaf implements Component {
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void show() {
System.out.println("Leaf: " + name);
}
}
// 容器节点:可以包含子组件
class Composite implements Component {
private String name;
private List<Component> children = new ArrayList<>();
public Composite(String name) {
this.name = name;
}
// 添加子组件
public void add(Component component) {
children.add(component);
}
@Override
public void show() {
System.out.println("Composite: " + name);
for (Component component : children) {
component.show();
}
}
}
// 测试
public class CompositeDemo {
public static void main(String[] args) {
Composite root = new Composite("Root");
Leaf leaf1 = new Leaf("Leaf 1");
Leaf leaf2 = new Leaf("Leaf 2");
root.add(leaf1);
root.add(leaf2);
Composite subComposite = new Composite("Sub Composite");
subComposite.add(new Leaf("Leaf 3"));
root.add(subComposite);
root.show();
}
}
|
文件夹场景版代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
import java.util.ArrayList;
// 抽象组件:统一规范文件和文件夹行为
abstract class Component {
protected String name;
public Component(String name) {
this.name = name;
}
public void add(Component component) {
throw new UnsupportedOperationException();
}
public void remove(Component component) {
throw new UnsupportedOperationException();
}
public Component getChild(int index) {
throw new UnsupportedOperationException();
}
public abstract void operation();
}
// 叶子节点:文件
class Leaf extends Component {
public Leaf(String name) {
super(name);
}
@Override
public void operation() {
System.out.println("执行单个对象 " + name + " 的操作");
}
}
// 容器节点:文件夹
class Composite extends Component {
private ArrayList<Component> children = new ArrayList<>();
public Composite(String name) {
super(name);
}
@Override
public void add(Component component) {
children.add(component);
}
@Override
public void remove(Component component) {
children.remove(component);
}
@Override
public Component getChild(int index) {
return children.get(index);
}
@Override
public void operation() {
System.out.println("执行组合对象 " + name + " 的操作");
for (Component component : children) {
component.operation();
}
}
}
// 客户端测试
public class CompositeDemo2 {
public static void main(String[] args) {
Composite root = new Composite("根文件夹");
Leaf file1 = new Leaf("文件1");
Leaf file2 = new Leaf("文件2");
Composite subFolder = new Composite("子文件夹");
root.add(file1);
root.add(file2);
root.add(subFolder);
Leaf file3 = new Leaf("文件3");
subFolder.add(file3);
root.operation();
}
}
|
4. 装饰器模式
一、核心模型
现实模型:汉堡 / 咖啡加配料
基础汉堡/咖啡是核心对象,生菜、芝士、牛奶、糖都是动态配料;
不用创建无数子类,而是一层一层包裹,动态给对象加功能。
核心对应:
- 基础对象:原味汉堡、黑咖啡
- 装饰器:配料(生菜、芝士、牛奶、糖)
- 特点:层层包裹、动态增强、不修改原类
二、原理描述
在不改变原有对象的前提下,动态地给对象添加额外功能;
通过组合包裹的方式,一层一层装饰,比继承更灵活。
三、核心特点
- 动态增强对象功能
- 避免子类爆炸
- 装饰与被装饰实现同一接口
- 可多层嵌套装饰
四、Java 实现
装饰器模式-咖啡版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
// 抽象组件接口
interface Coffee {
double cost();
String description();
}
// 具体组件:基础咖啡
class SimpleCoffee implements Coffee {
@Override
public double cost() {
return 5.0;
}
@Override
public String description() {
return "Simple Coffee";
}
}
// 装饰器抽象类
abstract class CoffeeDecorator implements Coffee {
protected Coffee decoratedCoffee;
public CoffeeDecorator(Coffee coffee) {
this.decoratedCoffee = coffee;
}
@Override
public double cost() {
return decoratedCoffee.cost();
}
@Override
public String description() {
return decoratedCoffee.description();
}
}
// 具体装饰器:加牛奶
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double cost() {
return super.cost() + 1.5;
}
@Override
public String description() {
return super.description() + ", with milk";
}
}
// 具体装饰器:加糖
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public double cost() {
return super.cost() + 0.5;
}
@Override
public String description() {
return super.description() + ", with sugar";
}
}
// 测试
public class DecoratorDemo {
public static void main(String[] args) {
Coffee coffee = new SimpleCoffee();
System.out.println(coffee.description() + " $" + coffee.cost());
coffee = new MilkDecorator(coffee);
System.out.println(coffee.description() + " $" + coffee.cost());
coffee = new SugarDecorator(coffee);
System.out.println(coffee.description() + " $" + coffee.cost());
}
}
|
装饰器模式-汉堡版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
// 汉堡接口
interface Burger {
String getDescription();
double getCost();
}
// 基础汉堡
class BasicBurger implements Burger {
@Override
public String getDescription() {
return "基础汉堡(面包夹肉饼)";
}
@Override
public double getCost() {
return 10.0;
}
}
// 装饰器抽象类
abstract class BurgerDecorator implements Burger {
protected Burger burger;
public BurgerDecorator(Burger burger) {
this.burger = burger;
}
@Override
public String getDescription() {
return burger.getDescription();
}
@Override
public double getCost() {
return burger.getCost();
}
}
// 生菜装饰器
class LettuceDecorator extends BurgerDecorator {
public LettuceDecorator(Burger burger) {
super(burger);
}
@Override
public String getDescription() {
return burger.getDescription() + " + 生菜";
}
@Override
public double getCost() {
return burger.getCost() + 2.0;
}
}
// 芝士装饰器
class CheeseDecorator extends BurgerDecorator {
public CheeseDecorator(Burger burger) {
super(burger);
}
@Override
public String getDescription() {
return burger.getDescription() + " + 芝士";
}
@Override
public double getCost() {
return burger.getCost() + 3.0;
}
}
// 客户端
public class DecoratorPatternExample {
public static void main(String[] args) {
Burger basicBurger = new BasicBurger();
System.out.println(basicBurger.getDescription() + ",价格:" + basicBurger.getCost());
Burger lettuceBurger = new LettuceDecorator(basicBurger);
System.out.println(lettuceBurger.getDescription() + ",价格:" + lettuceBurger.getCost());
Burger lettuceCheeseBurger = new CheeseDecorator(lettuceBurger);
System.out.println(lettuceCheeseBurger.getDescription() + ",价格:" + lettuceCheeseBurger.getCost());
}
}
|
5. 外观模式
一、核心模型
现实模型:医院导医台 / 电脑开机
系统内部很复杂(挂号、诊断、检查、拿药),
给用户一个简单入口,不用关心内部细节。
核心对应:
- 复杂子系统:医院各个部门、电脑硬件
- 外观类:导医台、电脑开机键
- 作用:统一入口、简化调用、隐藏复杂流程
二、原理描述
为复杂子系统提供一个统一高层接口,让客户端更简单地使用系统;
隐藏内部复杂性,只暴露简单易用的入口。
三、核心特点
- 简化复杂调用
- 解耦客户端与子系统
- 提供统一入口
- 不修改子系统,只做封装
四、Java 实现
外观模式-电脑版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
// 子系统类1
class CPU {
public void start() {
System.out.println("CPU starting...");
}
public void shutdown() {
System.out.println("CPU shutting down...");
}
}
// 子系统类2
class Memory {
public void load() {
System.out.println("Memory loading...");
}
public void clear() {
System.out.println("Memory clearing...");
}
}
// 子系统类3
class HardDrive {
public void read() {
System.out.println("HardDrive reading...");
}
public void write() {
System.out.println("HardDrive writing...");
}
}
// 外观类
class ComputerFacade {
private CPU cpu;
private Memory memory;
private HardDrive hardDrive;
public ComputerFacade() {
cpu = new CPU();
memory = new Memory();
hardDrive = new HardDrive();
}
public void startComputer() {
System.out.println("Starting computer...");
cpu.start();
memory.load();
hardDrive.read();
}
public void shutdownComputer() {
System.out.println("Shutting down computer...");
cpu.shutdown();
memory.clear();
hardDrive.write();
}
}
// 测试
public class FacadeDemo {
public static void main(String[] args) {
ComputerFacade computer = new ComputerFacade();
computer.startComputer();
computer.shutdownComputer();
}
}
|
外观模式-医院版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
// 挂号处
class RegistrationDesk {
public void register() {
System.out.println("在挂号处完成挂号");
}
}
// 科室
class Department {
public void diagnose() {
System.out.println("在科室进行病情诊断");
}
}
// 检验科
class Laboratory {
public void test() {
System.out.println("在检验科进行检查");
}
}
// 药房
class Pharmacy {
public void getMedicine() {
System.out.println("在药房领取药品");
}
}
// 导诊台外观类
class GuideDeskFacade {
private RegistrationDesk registrationDesk;
private Department department;
private Laboratory laboratory;
private Pharmacy pharmacy;
public GuideDeskFacade() {
registrationDesk = new RegistrationDesk();
department = new Department();
laboratory = new Laboratory();
pharmacy = new Pharmacy();
}
public void seeDoctor() {
registrationDesk.register();
department.diagnose();
laboratory.test();
pharmacy.getMedicine();
System.out.println("看病流程完成");
}
}
// 客户端
public class HospitalGuideDeskExample {
public static void main(String[] args) {
GuideDeskFacade guideDesk = new GuideDeskFacade();
guideDesk.seeDoctor();
}
}
|
6. 享元模式
一、核心模型
现实模型:共享单车 / 画图工具
大量重复对象(同颜色、同型号),只创建一份共享;
不同位置/状态作为外部信息传入,节省内存。
核心对应:
- 共享内部状态:颜色、车型
- 外部状态:位置、坐标
- 工厂:统一管理共享对象
二、原理描述
运用共享技术,大量复用细粒度对象,
把可共享的部分(内部状态) 与独立部分(外部状态) 分离,
大幅减少对象数量,节省内存。
三、核心特点
- 共享相同对象,减少内存
- 区分内部状态、外部状态
- 使用工厂统一管理共享池
- 适合大量重复对象场景
四、Java 实现
享元模式-画图版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
import java.util.HashMap;
import java.util.Map;
// 享元接口
interface Shape {
void draw();
}
// 具体享元类
class Circle implements Shape {
private String color; // 内部状态(共享)
private int x, y, radius;
public Circle(String color) {
this.color = color;
}
public void setX(int x) { this.x = x; }
public void setY(int y) { this.y = y; }
public void setRadius(int radius) { this.radius = radius; }
@Override
public void draw() {
System.out.println("Drawing circle [Color: " + color + ", x: " + x + ", y: " + y + ", radius: " + radius + "]");
}
}
// 享元工厂
class ShapeFactory {
private static final Map<String, Shape> circleMap = new HashMap<>();
public static Shape getCircle(String color) {
Circle circle = (Circle) circleMap.get(color);
if (circle == null) {
circle = new Circle(color);
circleMap.put(color, circle);
}
return circle;
}
}
// 测试
public class FlyweightDemo {
public static void main(String[] args) {
Circle circle1 = (Circle) ShapeFactory.getCircle("Red");
circle1.setX(10);
circle1.setY(20);
circle1.setRadius(5);
circle1.draw();
Circle circle2 = (Circle) ShapeFactory.getCircle("Red");
circle2.setX(30);
circle2.setY(40);
circle2.setRadius(10);
circle2.draw();
System.out.println("同一对象: " + (circle1 == circle2));
}
}
|
享元模式-共享单车版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
import java.util.HashMap;
import java.util.Map;
interface Bike {
void ride(String location);
}
class SharedBike implements Bike {
private String model;
private String color;
public SharedBike(String model, String color) {
this.model = model;
this.color = color;
}
@Override
public void ride(String location) {
System.out.println("骑 " + color + " " + model + ",位置: " + location);
}
}
class BikeFactory {
private static Map<String, Bike> bikeMap = new HashMap<>();
public static Bike getBike(String model, String color) {
String key = model + "-" + color;
if (!bikeMap.containsKey(key)) {
bikeMap.put(key, new SharedBike(model, color));
}
return bikeMap.get(key);
}
}
public class FlyweightDemo {
public static void main(String[] args) {
SharedBike bike1 = (SharedBike) BikeFactory.getBike("山地车", "蓝色");
bike1.ride("公园门口");
SharedBike bike2 = (SharedBike) BikeFactory.getBike("山地车", "蓝色");
bike2.ride("商场门口");
System.out.println("同一对象: " + (bike1 == bike2));
}
}
|
7. 代理模式
一、核心模型
现实模型:房屋中介 / 图片懒加载
不直接访问真实对象,而是通过代理对象间接访问;
代理可做:权限控制、延迟加载、日志、增强功能。
核心对应:
- 真实对象:房东、真实图片
- 代理对象:中介、代理图片
- 作用:控制访问、增强功能、延迟加载
二、原理描述
为一个对象提供一个代理,由代理控制对原对象的访问;
可在调用前后做增强,不修改原对象。
三、核心特点
- 保护/控制真实对象访问
- 可延迟加载(懒加载)
- 可增强功能(日志、权限、缓存)
- 代理与真实对象实现同一接口
四、Java 实现
代理模式-图片版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
// 抽象主题接口
interface Image {
void display();
}
// 真实主题
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading " + filename);
}
@Override
public void display() {
System.out.println("Displaying " + filename);
}
}
// 代理类
class ProxyImage implements Image {
private String filename;
private RealImage realImage;
public ProxyImage(String filename) {
this.filename = filename;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
// 测试
public class ProxyDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test_image.jpg");
image.display(); // 懒加载(延迟加载)
image.display(); // 缓存(复用对象)
}
}
|
代理模式-租房版
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
// 租房接口
interface RentHouse {
void rent();
}
// 房东(真实对象)
class Landlord implements RentHouse {
@Override
public void rent() {
System.out.println("房东出租房子");
}
}
// 中介(代理对象)
class HouseAgent implements RentHouse {
private Landlord landlord;
public HouseAgent(Landlord landlord) {
this.landlord = landlord;
}
@Override
public void rent() {
System.out.println("中介筛选房子");
System.out.println("中介安排看房");
landlord.rent();
System.out.println("中介协助签合同");
}
}
// 客户端
public class ProxyPatternExample {
public static void main(String[] args) {
Landlord landlord = new Landlord();
HouseAgent agent = new HouseAgent(landlord);
agent.rent();
}
}
|
三、行为型模式
1. 责任链模式
一、核心模型
现实模型:公司请假审批
请假天数不同,审批人不同(项目经理→部门经理→总经理),请假申请沿审批链传递,直到有审批人能处理。
核心对应:
- 责任链:项目经理→部门经理→总经理(依次传递)
- 请求:请假申请(天数不同,处理者不同)
- 特点:请求沿链传递、谁能处理谁处理、不直接耦合
二、原理描述
将多个处理者组成一条责任链,请求沿着这条链依次传递,直到有一个处理者能够处理该请求;
每个处理者只负责自己权限范围内的请求,无权处理则传递给下一个处理者,降低请求发送者与处理者的耦合。
三、核心特点
- 请求沿责任链传递,无需知道具体处理者
- 每个处理者只处理自己职责内的请求
- 可动态调整责任链顺序和处理者
- 避免请求发送者与多个处理者直接耦合
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
// 抽象处理者
abstract class Handler {
protected Handler next;
public void setNext(Handler next) {
this.next = next;
}
public abstract void handleRequest(String request);
}
// 具体处理者A
class ConcreteHandlerA extends Handler {
@Override
public void handleRequest(String request) {
if (request.contains("A")) {
System.out.println("Handler A processed the request: " + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
// 具体处理者B
class ConcreteHandlerB extends Handler {
@Override
public void handleRequest(String request) {
if (request.contains("B")) {
System.out.println("Handler B processed the request: " + request);
} else if (next != null) {
next.handleRequest(request);
}
}
}
// 测试
public class ChainOfResponsibilityDemo {
public static void main(String[] args) {
Handler handlerA = new ConcreteHandlerA();
Handler handlerB = new ConcreteHandlerB();
handlerA.setNext(handlerB);
handlerA.handleRequest("Request for A");
handlerA.handleRequest("Request for B");
handlerA.handleRequest("Request for C");
}
}
|
责任链模式-请假
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
// 抽象处理者类
abstract class Approver {
protected Approver nextApprover;
public void setNextApprover(Approver nextApprover) {
this.nextApprover = nextApprover;
}
public abstract void processRequest(int days);
}
// 项目经理类
class ProjectManager extends Approver {
@Override
public void processRequest(int days) {
if (days <= 1) {
System.out.println("项目经理批准了 " + days + " 天的请假申请。");
} else if (nextApprover != null) {
nextApprover.processRequest(days);
}
}
}
// 部门经理类
class DepartmentManager extends Approver {
@Override
public void processRequest(int days) {
if (days > 1 && days <= 3) {
System.out.println("部门经理批准了 " + days + " 天的请假申请。");
} else if (nextApprover != null) {
nextApprover.processRequest(days);
}
}
}
// 总经理类
class GeneralManager extends Approver {
@Override
public void processRequest(int days) {
if (days > 3) {
System.out.println("总经理批准了 " + days + " 天的请假申请。");
}
}
}
// 客户端类
public class LeaveApprovalChain {
public static void main(String[] args) {
// 创建各个审批者
Approver projectManager = new ProjectManager();
Approver departmentManager = new DepartmentManager();
Approver generalManager = new GeneralManager();
// 设置责任链顺序
projectManager.setNextApprover(departmentManager);
departmentManager.setNextApprover(generalManager);
// 模拟不同天数的请假申请
projectManager.processRequest(1);
projectManager.processRequest(2);
projectManager.processRequest(5);
}
}
|
2. 命令模式
一、核心模型
现实模型:餐厅点餐
顾客(客户端)点餐,服务员(调用者)记录订单(命令),厨师(接收者)按订单做菜;顾客无需直接找厨师,服务员统一调度订单。
核心对应:
- 命令:订单(封装点餐请求)
- 调用者:服务员(管理、执行命令)
- 接收者:厨师(执行具体操作)
- 特点:请求封装、解耦客户端与接收者
二、原理描述
将请求封装成独立的命令对象,使请求的发送者(客户端)与接收者(执行请求的对象)解耦;
命令对象可被存储、排队、记录日志,实现请求的灵活调度(顺序执行、撤销)。
三、核心特点
- 解耦请求发送者与接收者,互不依赖
- 请求被封装成命令对象,可灵活管理(排队、日志、撤销)
- 可扩展新命令,无需修改原有调用者和接收者
- 调用者只需调用命令的执行方法,无需关心具体实现
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
// 命令接口
interface Command {
void execute();
}
// 具体命令
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
}
// 接收者
class Light {
public void on() {
System.out.println("Light is ON");
}
public void off() {
System.out.println("Light is OFF");
}
}
// 调用者
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}
// 测试
public class CommandDemo {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();
}
}
|
命令模式-餐厅点餐
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
// 命令接口
interface Command {
void execute();
}
// 具体命令类:点炒饭
class FriedRiceCommand implements Command {
private Chef chef;
public FriedRiceCommand(Chef chef) {
this.chef = chef;
}
@Override
public void execute() {
chef.cookFriedRice();
}
}
// 具体命令类:点炒面
class FriedNoodlesCommand implements Command {
private Chef chef;
public FriedNoodlesCommand(Chef chef) {
this.chef = chef;
}
@Override
public void execute() {
chef.cookFriedNoodles();
}
}
// 厨师类,负责执行具体的做菜操作
class Chef {
public void cookFriedRice() {
System.out.println("厨师正在做炒饭");
}
public void cookFriedNoodles() {
System.out.println("厨师正在做炒面");
}
}
// 服务员类,负责接收、排队和执行命令
class Waiter {
private Command command;
public void takeOrder(Command command) {
this.command = command;
}
public void placeOrder() {
if (command != null) {
command.execute();
}
}
}
// 客户端类
public class RestaurantCommandPattern {
public static void main(String[] args) {
Chef chef = new Chef();
Waiter waiter = new Waiter();
Command friedRiceCommand = new FriedRiceCommand(chef);
waiter.takeOrder(friedRiceCommand);
waiter.placeOrder();
Command friedNoodlesCommand = new FriedNoodlesCommand(chef);
waiter.takeOrder(friedNoodlesCommand);
waiter.placeOrder();
}
}
|
3. 解释器模式
一、核心模型
现实模型:简单数学表达式计算器
小学课堂上,老师(解释器)根据语法规则,计算「2+3」「5-1」等表达式;数字和运算符是语法元素,老师按规则解释计算。
核心对应:
- 抽象表达式:语法规则抽象
- 具体表达式:数字、加减运算符
- 解释器:解析表达式、计算结果
- 特点:解析特定语法、可扩展语法规则
二、原理描述
定义一种语言的语法规则,构建解释器解析这种语言的句子(数学表达式、简单指令);
将语法拆分为抽象表达式和具体表达式,递归调用解释器完成解析与执行。
三、核心特点
- 专门用于解析特定语法场景(表达式、配置文件)
- 语法规则可通过新增具体表达式扩展
- 语法简单易用,复杂语法会导致类爆炸
- 核心:解析语法、执行逻辑
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
// 抽象表达式接口
interface Expression {
boolean interpret(String context);
}
// 终结符表达式
class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data) {
this.data = data;
}
@Override
public boolean interpret(String context) {
return context.contains(data);
}
}
// 非终结符表达式:或表达式
class OrExpression implements Expression {
private Expression expr1;
private Expression expr2;
public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}
// 测试
public class InterpreterDemo {
public static void main(String[] args) {
Expression isAdmin = new TerminalExpression("Admin");
Expression isManager = new TerminalExpression("Manager");
Expression isAdminOrManager = new OrExpression(isAdmin, isManager);
System.out.println("User is admin or manager? " + isAdminOrManager.interpret("Admin"));
}
}
|
解释器模式-数学表达式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
// 抽象表达式类
abstract class Expression {
public abstract int interpret();
}
// 数字表达式类
class NumberExpression extends Expression {
private int number;
public NumberExpression(int number) {
this.number = number;
}
@Override
public int interpret() {
return number;
}
}
// 加法表达式类
class AdditionExpression extends Expression {
private Expression left;
private Expression right;
public AdditionExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() + right.interpret();
}
}
// 减法表达式类
class SubtractionExpression extends Expression {
private Expression left;
private Expression right;
public SubtractionExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() - right.interpret();
}
}
// 客户端类
public class InterpreterPatternExample {
public static void main(String[] args) {
Expression expression = new AdditionExpression(
new NumberExpression(2),
new NumberExpression(3)
);
int result = expression.interpret();
System.out.println("表达式 2 + 3 的结果是: " + result);
Expression subtractionExpression = new SubtractionExpression(
new NumberExpression(5),
new NumberExpression(1)
);
int subtractionResult = subtractionExpression.interpret();
System.out.println("表达式 5 - 1 的结果是: " + subtractionResult);
}
}
|
4. 迭代器模式
一、核心模型
现实模型:图书馆书架书籍遍历
管理员通过迭代器(遍历工具)遍历书架(聚合对象)书籍,无需知道书架内部存储结构。
核心对应:
- 聚合对象:书架
- 迭代器:遍历工具(hasNext、next)
- 元素:书籍
- 特点:遍历与存储分离、隐藏内部结构
二、原理描述
提供统一方式遍历聚合对象,将遍历逻辑从聚合对象中分离;
客户端无需了解集合内部存储结构,即可统一遍历元素。
三、核心特点
- 解耦聚合对象与遍历操作
- 统一遍历接口,适配不同集合
- 可扩展正向/反向等自定义迭代器
- 隐藏集合内部实现细节
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
// 集合类
class NameRepository implements Iterable<String> {
private List<String> names = new ArrayList<>();
public NameRepository() {
names.add("Alice");
names.add("Bob");
names.add("Charlie");
}
@Override
public Iterator<String> iterator() {
return names.iterator();
}
}
// 测试
public class IteratorDemo {
public static void main(String[] args) {
NameRepository names = new NameRepository();
for (String name : names) {
System.out.println(name);
}
}
}
|
迭代器模式-书架
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
import java.util.ArrayList;
import java.util.List;
// 书籍类
class Book {
private String title;
public Book(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}
// 迭代器接口
interface Iterator {
boolean hasNext();
Book next();
}
// 书架类,聚合对象
class Bookshelf {
private List<Book> books = new ArrayList<>();
public void addBook(Book book) {
books.add(book);
}
public Iterator createIterator() {
return new BookshelfIterator();
}
// 迭代器内部类
private class BookshelfIterator implements Iterator {
private int index = 0;
@Override
public boolean hasNext() {
return index < books.size();
}
@Override
public Book next() {
Book book = books.get(index);
index++;
return book;
}
}
}
// 客户端类
public class IteratorPatternExample {
public static void main(String[] args) {
Bookshelf bookshelf = new Bookshelf();
bookshelf.addBook(new Book("Book 1"));
bookshelf.addBook(new Book("Book 2"));
bookshelf.addBook(new Book("Book 3"));
Iterator iterator = bookshelf.createIterator();
while (iterator.hasNext()) {
Book book = iterator.next();
System.out.println("当前书籍: " + book.getTitle());
}
}
}
|
5. 中介者模式
一、核心模型
现实模型:机场塔台调度
多架飞机无需直接通信,通过塔台统一协调起降;飞机只和塔台交互,避免网状依赖。
核心对应:
- 中介者:机场塔台
- 同事对象:各架飞机
- 特点:统一协调、解耦同事、集中管理交互
二、原理描述
定义中介者对象,封装多个同事对象的交互逻辑;
同事之间不直接通信,全部通过中介者中转,降低耦合度。
三、核心特点
- 消除同事间网状依赖,改为星型依赖
- 交互逻辑集中在中介者,便于维护
- 新增同事只需适配中介者,不改动其他同事
- 缺点:中介者易逻辑臃肿,成为上帝类
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
import java.util.ArrayList;
import java.util.List;
// 抽象中介者
interface ChatMediator {
void sendMessage(String msg, User user);
void addUser(User user);
}
// 具体中介者
class ChatMediatorImpl implements ChatMediator {
private List<User> users = new ArrayList<>();
@Override
public void addUser(User user) {
users.add(user);
}
@Override
public void sendMessage(String msg, User user) {
for (User u : users) {
if (u != user) {
u.receive(msg);
}
}
}
}
// 同事类
abstract class User {
protected ChatMediator mediator;
protected String name;
public User(ChatMediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public abstract void send(String msg);
public abstract void receive(String msg);
}
// 具体同事类
class ChatUser extends User {
public ChatUser(ChatMediator mediator, String name) {
super(mediator, name);
}
@Override
public void send(String msg) {
System.out.println(name + " sends: " + msg);
mediator.sendMessage(msg, this);
}
@Override
public void receive(String msg) {
System.out.println(name + " receives: " + msg);
}
}
// 测试
public class MediatorDemo {
public static void main(String[] args) {
ChatMediator mediator = new ChatMediatorImpl();
User user1 = new ChatUser(mediator, "Alice");
User user2 = new ChatUser(mediator, "Bob");
User user3 = new ChatUser(mediator, "Charlie");
mediator.addUser(user1);
mediator.addUser(user2);
mediator.addUser(user3);
user1.send("Hello everyone!");
}
}
|
中介者模式-飞机塔台
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
import java.util.ArrayList;
import java.util.List;
// 飞机抽象类
abstract class Plane {
protected AirportTower tower;
protected String name;
public Plane(AirportTower tower, String name) {
this.tower = tower;
this.name = name;
}
public abstract void sendRequest(String message);
public abstract void receiveMessage(String message);
}
// 具体飞机类
class ConcretePlane extends Plane {
public ConcretePlane(AirportTower tower, String name) {
super(tower, name);
}
@Override
public void sendRequest(String message) {
System.out.println(name + " 发送请求: " + message);
tower.notifyPlanes(this, message);
}
@Override
public void receiveMessage(String message) {
System.out.println(name + " 收到消息: " + message);
}
}
// 机场塔台类(中介者)
class AirportTower {
private List<Plane> planes = new ArrayList<>();
public void registerPlane(Plane plane) {
planes.add(plane);
}
public void notifyPlanes(Plane sender, String message) {
for (Plane plane : planes) {
if (plane != sender) {
plane.receiveMessage(sender.name + " 说: " + message);
}
}
}
}
// 客户端类
public class AirportMediatorPattern {
public static void main(String[] args) {
AirportTower tower = new AirportTower();
Plane plane1 = new ConcretePlane(tower, "飞机1");
Plane plane2 = new ConcretePlane(tower, "飞机2");
Plane plane3 = new ConcretePlane(tower, "飞机3");
tower.registerPlane(plane1);
tower.registerPlane(plane2);
tower.registerPlane(plane3);
plane1.sendRequest("我准备起飞");
}
}
|
6. 备忘录模式
一、核心模型
现实模型:文档编辑撤销功能
Word编辑文档,每步操作保存状态快照,撤销可回滚到历史版本;
发起人(文档)、备忘录(状态快照)、管理者(保管快照)三者协作。
核心对应:
- 发起人:文档(创建/恢复状态)
- 备忘录:存储对象内部状态
- 管理者:保管、存取备忘录
- 特点:状态备份、可撤销、不破坏封装
二、原理描述
在不破坏封装的前提下,捕获对象内部状态并保存;
后续可通过保存的备忘录,将对象回滚到历史状态,实现撤销、回滚。
三、核心特点
- 支持对象状态备份与回滚、撤销操作
- 不对外暴露内部字段,保持封装性
- 备忘录只读,仅发起人可恢复
- 管理者只负责保管,不修改备忘录内容
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
import java.util.Stack;
// 发起人
class Originator {
private String state;
public void setState(String state) {
this.state = state;
System.out.println("Setting state to " + state);
}
public String getState() {
return state;
}
public Memento saveStateToMemento() {
return new Memento(state);
}
public void getStateFromMemento(Memento memento) {
state = memento.getState();
System.out.println("State restored to " + state);
}
}
// 备忘录
class Memento {
private final String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 管理者
class Caretaker {
private Stack<Memento> mementoStack = new Stack<>();
public void add(Memento state){
mementoStack.push(state);
}
public Memento get(){
return mementoStack.pop();
}
}
// 测试
public class MementoDemo {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("State1");
caretaker.add(originator.saveStateToMemento());
originator.setState("State2");
caretaker.add(originator.saveStateToMemento());
originator.setState("State3");
originator.getStateFromMemento(caretaker.get());
}
}
|
备忘录模式-文档撤销
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
// 备忘录类,存储文档状态
class DocumentMemento {
private String content;
public DocumentMemento(String content) {
this.content = content;
}
public String getContent() {
return content;
}
}
// 文档类(发起人)
class Document {
private String content;
private Caretaker caretaker;
public Document(Caretaker caretaker) {
this.caretaker = caretaker;
}
public void setContent(String content) {
this.content = content;
caretaker.saveMemento(createMemento());
}
public String getContent() {
return content;
}
public DocumentMemento createMemento() {
return new DocumentMemento(content);
}
public void restoreFromMemento(DocumentMemento memento) {
this.content = memento.getContent();
}
public void undo() {
DocumentMemento memento = caretaker.getPreviousMemento();
if (memento != null) {
restoreFromMemento(memento);
}
}
}
// 管理者类
class Caretaker {
private java.util.List<DocumentMemento> mementos = new java.util.ArrayList<>();
private int currentIndex = -1;
public void saveMemento(DocumentMemento memento) {
if (currentIndex < mementos.size() - 1) {
mementos = mementos.subList(0, currentIndex + 1);
}
mementos.add(memento);
currentIndex++;
}
public DocumentMemento getPreviousMemento() {
if (currentIndex > 0) {
currentIndex--;
return mementos.get(currentIndex);
}
return null;
}
}
// 客户端类
public class DocumentMementoPattern {
public static void main(String[] args) {
Caretaker caretaker = new Caretaker();
Document document = new Document(caretaker);
document.setContent("第一段文字");
System.out.println("当前内容: " + document.getContent());
document.setContent("第一段文字,第二段文字");
System.out.println("当前内容: " + document.getContent());
document.undo();
System.out.println("撤销后内容: " + document.getContent());
}
}
|
7. 观察者模式
一、核心模型
现实模型:天气预报
气象站(主题)发布天气,手机APP、电视台(观察者)订阅;主题状态变更,自动推送所有观察者更新。
核心对应:
- 主题:被观察者,维护观察者列表
- 观察者:订阅者,接收通知自动更新
- 特点:一对多、发布-订阅、自动通知
二、原理描述
定义一对多依赖,一个主题绑定多个观察者;
主题状态变化时,自动广播通知所有观察者,观察者被动更新自身状态。
三、核心特点
- 典型发布-订阅模型,一对多联动
- 观察者可动态订阅/取消订阅
- 主题与观察者松耦合,互不依赖具体实现
- 适合事件广播、消息推送场景
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
import java.util.ArrayList;
import java.util.List;
// 主题接口
interface Subject {
void attach(Observer o);
void detach(Observer o);
void notifyObservers();
}
// 观察者接口
interface Observer {
void update(String message);
}
// 具体主题
class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private String state;
public void setState(String state) {
this.state = state;
notifyObservers();
}
@Override
public void attach(Observer o) {
observers.add(o);
}
@Override
public void detach(Observer o) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for (Observer o : observers) {
o.update(state);
}
}
}
// 具体观察者
class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " received update: " + message);
}
}
// 测试
public class ObserverDemo {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer obs1 = new ConcreteObserver("Observer1");
Observer obs2 = new ConcreteObserver("Observer2");
subject.attach(obs1);
subject.attach(obs2);
subject.setState("New State");
}
}
|
观察者模式-天气预报
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
import java.util.ArrayList;
import java.util.List;
// 观察者接口
interface Observer {
void update(String weatherInfo);
}
// 主题接口
interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// 具体主题类:气象站
class WeatherStation implements Subject {
private List<Observer> observers = new ArrayList<>();
private String weatherInfo;
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(weatherInfo);
}
}
public void setWeatherInfo(String weatherInfo) {
this.weatherInfo = weatherInfo;
notifyObservers();
}
}
// 具体观察者:手机天气应用
class MobileWeatherApp implements Observer {
@Override
public void update(String weatherInfo) {
System.out.println("手机天气应用收到更新:" + weatherInfo);
}
}
// 具体观察者:电视台
class TVStation implements Observer {
@Override
public void update(String weatherInfo) {
System.out.println("电视台收到更新:" + weatherInfo);
}
}
// 客户端类
public class WeatherForecastObserver {
public static void main(String[] args) {
WeatherStation weatherStation = new WeatherStation();
MobileWeatherApp mobileApp = new MobileWeatherApp();
TVStation tvStation = new TVStation();
weatherStation.registerObserver(mobileApp);
weatherStation.registerObserver(tvStation);
weatherStation.setWeatherInfo("今天有雨");
}
}
|
8. 状态模式
一、核心模型
现实模型:自动售货机
售货机有待机、投币、出货多种状态;不同状态下同一操作响应不同,状态自动流转。
核心对应:
- 上下文:自动售货机,持有当前状态
- 状态接口:统一行为规范
- 具体状态:待机/投币/出货,各自封装行为
- 特点:状态驱动行为、消除大量if-else
二、原理描述
将不同状态的行为封装到独立状态类,上下文委托当前状态处理请求;
对象行为随状态自动变化,新增状态无需修改原有上下文代码。
三、核心特点
- 把状态和行为绑定,逻辑拆分清晰
- 消除臃肿的if-else状态判断
- 符合开闭原则,新增状态只加新类
- 状态流转由状态类自身控制,解耦上下文
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
// 状态接口
interface State {
void doAction(Context context);
}
// 具体状态A
class StateA implements State {
@Override
public void doAction(Context context) {
System.out.println("State A handling request, switching to State B");
context.setState(new StateB());
}
}
// 具体状态B
class StateB implements State {
@Override
public void doAction(Context context) {
System.out.println("State B handling request, switching to State A");
context.setState(new StateA());
}
}
// 上下文类
class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.doAction(this);
}
}
// 测试
public class StateDemo {
public static void main(String[] args) {
Context context = new Context(new StateA());
context.request();
context.request();
}
}
|
状态模式-自动售货机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
// 状态接口
interface VendingMachineState {
void insertCoin(VendingMachine vendingMachine);
void selectProduct(VendingMachine vendingMachine);
void dispenseProduct(VendingMachine vendingMachine);
void refund(VendingMachine vendingMachine);
}
// 待机状态类
class StandbyState implements VendingMachineState {
@Override
public void insertCoin(VendingMachine vendingMachine) {
System.out.println("硬币已投入,进入投币状态");
vendingMachine.setState(new CoinInsertedState());
}
@Override
public void selectProduct(VendingMachine vendingMachine) {
System.out.println("请先投币");
}
@Override
public void dispenseProduct(VendingMachine vendingMachine) {
System.out.println("请先投币并选择商品");
}
@Override
public void refund(VendingMachine vendingMachine) {
System.out.println("您还未投币,无需退款");
}
}
// 投币状态类
class CoinInsertedState implements VendingMachineState {
@Override
public void insertCoin(VendingMachine vendingMachine) {
System.out.println("您已经投过币了,可直接选择商品");
}
@Override
public void selectProduct(VendingMachine vendingMachine) {
System.out.println("商品已选择,准备出货");
vendingMachine.setState(new DispensingState());
}
@Override
public void dispenseProduct(VendingMachine vendingMachine) {
System.out.println("请先选择商品");
}
@Override
public void refund(VendingMachine vendingMachine) {
System.out.println("硬币已退还,回到待机状态");
vendingMachine.setState(new StandbyState());
}
}
// 出货状态类
class DispensingState implements VendingMachineState {
@Override
public void insertCoin(VendingMachine vendingMachine) {
System.out.println("正在出货,请稍等");
}
@Override
public void selectProduct(VendingMachine vendingMachine) {
System.out.println("正在出货,请稍等");
}
@Override
public void dispenseProduct(VendingMachine vendingMachine) {
System.out.println("商品已出货,回到待机状态");
vendingMachine.setState(new StandbyState());
}
@Override
public void refund(VendingMachine vendingMachine) {
System.out.println("正在出货,无法退款,请稍等");
}
}
// 上下文类:自动售货机
class VendingMachine {
private VendingMachineState currentState;
public VendingMachine() {
this.currentState = new StandbyState();
}
public void setState(VendingMachineState state) {
this.currentState = state;
}
public void insertCoin() {
currentState.insertCoin(this);
}
public void selectProduct() {
currentState.selectProduct(this);
}
public void dispenseProduct() {
currentState.dispenseProduct(this);
}
public void refund() {
currentState.refund(this);
}
}
// 客户端类
public class VendingMachineStatePattern {
public static void main(String[] args) {
VendingMachine vendingMachine = new VendingMachine();
vendingMachine.insertCoin();
vendingMachine.selectProduct();
vendingMachine.dispenseProduct();
}
}
|
9. 策略模式
一、核心模型
现实模型:出行方式选择
出行可切换步行、骑车、公交、打车;每种出行方式是一种独立算法,可随时替换,不改动出行主逻辑。
核心对应:
- 策略接口:统一算法规范
- 具体策略:各种出行方式/运算算法
- 上下文:持有策略、调度执行
- 特点:算法封装、可动态切换、解耦
二、原理描述
定义一族算法,每个算法封装为独立策略类;
算法可独立于客户端变化,客户端通过上下文动态切换策略,无需写大量条件判断。
三、核心特点
- 算法统一封装,相互可替换
- 算法与业务逻辑解耦
- 新增算法不用改上下文,符合开闭
- 彻底消除算法选择的if-else
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
// 策略接口
interface Strategy {
int doOperation(int num1, int num2);
}
// 加法策略
class OperationAdd implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
// 减法策略
class OperationSubtract implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
// 乘法策略
class OperationMultiply implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
// 上下文
class ContextStrategy {
private Strategy strategy;
public ContextStrategy(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
// 测试
public class StrategyDemo {
public static void main(String[] args) {
ContextStrategy context = new ContextStrategy(new OperationAdd());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
context = new ContextStrategy(new OperationSubtract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
context = new ContextStrategy(new OperationMultiply());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
|
策略模式-出行方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
// 策略接口
interface TravelStrategy {
void travel();
}
// 步行策略
class WalkStrategy implements TravelStrategy {
@Override
public void travel() {
System.out.println("选择步行出行,欣赏沿途风景");
}
}
// 骑行策略
class BikeStrategy implements TravelStrategy {
@Override
public void travel() {
System.out.println("选择骑自行车出行,灵活便捷");
}
}
// 公交策略
class BusStrategy implements TravelStrategy {
@Override
public void travel() {
System.out.println("选择乘坐公交车出行,经济实惠");
}
}
// 打车策略
class TaxiStrategy implements TravelStrategy {
@Override
public void travel() {
System.out.println("选择打车出行,快速高效");
}
}
// 上下文类
class TravelContext {
private TravelStrategy strategy;
public TravelContext(TravelStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(TravelStrategy strategy) {
this.strategy = strategy;
}
public void executeTravel() {
strategy.travel();
}
}
// 客户端类
public class TravelStrategyPattern {
public static void main(String[] args) {
TravelContext context = new TravelContext(new WalkStrategy());
context.executeTravel();
context.setStrategy(new BikeStrategy());
context.executeTravel();
context.setStrategy(new BusStrategy());
context.executeTravel();
context.setStrategy(new TaxiStrategy());
context.executeTravel();
}
}
|
10. 模板方法模式
一、核心模型
现实模型:制作咖啡和茶
制作饮品整体流程固定:烧水→备料→冲泡→加配料;
流程骨架在父类固定,可变步骤定义为抽象方法,由子类实现不同细节。
核心对应:
- 抽象模板类:定义固定流程骨架
- 模板方法:final 禁止重写,保证流程顺序
- 抽象步骤:由子类实现个性化逻辑
- 特点:骨架固定、步骤可扩展、复用流程
二、原理描述
在抽象类中定义算法流程骨架,固定执行顺序;
将可变步骤抽象为方法,延迟到子类实现,不改变整体流程即可定制不同步骤逻辑。
三、核心特点
- 流程骨架统一复用,减少重复代码
- 模板方法加 final,防止子类篡改流程
- 可变步骤由子类实现,灵活扩展
- 反向控制:父类调用子类方法
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
// 抽象类定义模板方法
abstract class Game {
// 模板方法:固定算法骨架
public final void play() {
initialize();
startPlay();
endPlay();
}
abstract void initialize();
abstract void startPlay();
abstract void endPlay();
}
// 具体子类
class FootballGame extends Game {
@Override
void initialize() {
System.out.println("Football Game Initialized! Start playing.");
}
@Override
void startPlay() {
System.out.println("Football Game Started. Enjoy the game!");
}
@Override
void endPlay() {
System.out.println("Football Game Finished!");
}
}
// 测试
public class TemplateMethodDemo {
public static void main(String[] args) {
Game game = new FootballGame();
game.play();
}
}
|
模板方法-泡茶咖啡
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
// 抽象模板类:制作饮品
abstract class BeverageMaker {
// 模板方法,固定流程
final void makeBeverage() {
boilWater();
prepareIngredients();
brew();
addCondiments();
System.out.println("一杯美味的饮品制作完成!");
}
// 通用固定步骤
void boilWater() {
System.out.println("正在烧水...");
}
// 抽象可变步骤
abstract void prepareIngredients();
abstract void brew();
abstract void addCondiments();
}
// 制作咖啡子类
class CoffeeMaker extends BeverageMaker {
@Override
void prepareIngredients() {
System.out.println("准备咖啡豆并研磨...");
}
@Override
void brew() {
System.out.println("用研磨好的咖啡豆冲泡咖啡...");
}
@Override
void addCondiments() {
System.out.println("添加牛奶和糖...");
}
}
// 制作茶子类
class TeaMaker extends BeverageMaker {
@Override
void prepareIngredients() {
System.out.println("准备茶叶...");
}
@Override
void brew() {
System.out.println("用热水浸泡茶叶...");
}
@Override
void addCondiments() {
System.out.println("添加柠檬片...");
}
}
// 客户端类
public class TemplateMethodPatternExample {
public static void main(String[] args) {
BeverageMaker coffeeMaker = new CoffeeMaker();
coffeeMaker.makeBeverage();
System.out.println("------------------");
BeverageMaker teaMaker = new TeaMaker();
teaMaker.makeBeverage();
}
}
|
11. 访问者模式
一、核心模型
现实模型:动物园动物体检
动物园有狮子、猴子、大象等动物;新增体检项目(健康检查、口腔检查)不用改动物类,新增访问者即可。
核心对应:
- 元素:动物类,提供接收访问者入口
- 访问者:体检类型,重载不同动物访问方法
- 对象结构:动物园,管理所有元素
- 特点:在不修改元素类的前提下新增操作
二、原理描述
将作用于元素的操作抽离为访问者,元素只提供接收访问者的入口;
新增操作只需新增访问者类,无需修改原有元素结构,适合数据结构固定、操作频繁变化的场景。
三、核心特点
- 元素类稳定,可动态新增操作
- 把相关操作集中到一个访问者类中
- 适合数据结构固定、行为易变场景
- 缺点:新增元素需修改所有访问者,违背开闭
四、Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
import java.util.ArrayList;
import java.util.List;
// 访问者接口
interface Visitor {
void visit(ElementA element);
void visit(ElementB element);
}
// 元素接口
interface Element {
void accept(Visitor visitor);
}
// 具体元素A
class ElementA implements Element {
public void operationA() {
System.out.println("ElementA operation");
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// 具体元素B
class ElementB implements Element {
public void operationB() {
System.out.println("ElementB operation");
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// 具体访问者
class ConcreteVisitor implements Visitor {
@Override
public void visit(ElementA element) {
System.out.println("Visitor processing ElementA");
element.operationA();
}
@Override
public void visit(ElementB element) {
System.out.println("Visitor processing ElementB");
element.operationB();
}
}
// 对象结构
class ObjectStructure {
private List<Element> elements = new ArrayList<>();
public void addElement(Element element) {
elements.add(element);
}
public void accept(Visitor visitor) {
for (Element element : elements) {
element.accept(visitor);
}
}
}
// 测试
public class VisitorDemo {
public static void main(String[] args) {
ObjectStructure structure = new ObjectStructure();
structure.addElement(new ElementA());
structure.addElement(new ElementB());
Visitor visitor = new ConcreteVisitor();
structure.accept(visitor);
}
}
|
访问者模式-动物园
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
import java.util.ArrayList;
import java.util.List;
// 动物元素接口
interface Animal {
void accept(Veterinarian visitor);
}
// 狮子
class Lion implements Animal {
@Override
public void accept(Veterinarian visitor) {
visitor.visit(this);
}
}
// 猴子
class Monkey implements Animal {
@Override
public void accept(Veterinarian visitor) {
visitor.visit(this);
}
}
// 大象
class Elephant implements Animal {
@Override
public void accept(Veterinarian visitor) {
visitor.visit(this);
}
}
// 访问者接口:兽医
interface Veterinarian {
void visit(Lion lion);
void visit(Monkey monkey);
void visit(Elephant elephant);
}
// 健康检查访问者
class HealthCheckVeterinarian implements Veterinarian {
@Override
public void visit(Lion lion) {
System.out.println("对狮子进行健康检查,检查肌肉力量。");
}
@Override
public void visit(Monkey monkey) {
System.out.println("对猴子进行健康检查,检查灵活性。");
}
@Override
public void visit(Elephant elephant) {
System.out.println("对大象进行健康检查,检查心脏功能。");
}
}
// 口腔检查访问者
class OralCheckVeterinarian implements Veterinarian {
@Override
public void visit(Lion lion) {
System.out.println("对狮子进行口腔检查,查看牙齿磨损情况。");
}
@Override
public void visit(Monkey monkey) {
System.out.println("对猴子进行口腔检查,查看牙龈健康。");
}
@Override
public void visit(Elephant elephant) {
System.out.println("对大象进行口腔检查,检查象牙状况。");
}
}
// 对象结构:动物园
class Zoo {
private List<Animal> animals = new ArrayList<>();
public void addAnimal(Animal animal) {
animals.add(animal);
}
public void accept(Veterinarian visitor) {
for (Animal animal : animals) {
animal.accept(visitor);
}
}
}
// 客户端
public class ZooVisitorPattern {
public static void main(String[] args) {
Zoo zoo = new Zoo();
zoo.addAnimal(new Lion());
zoo.addAnimal(new Monkey());
zoo.addAnimal(new Elephant());
HealthCheckVeterinarian healthCheck = new HealthCheckVeterinarian();
zoo.accept(healthCheck);
System.out.println("----------------------");
OralCheckVeterinarian oralCheck = new OralCheckVeterinarian();
zoo.accept(oralCheck);
}
}
|
总结
以上就是常见的 23 种设计模式,对加深封装、继承、多态、接口的理解帮助很多。这些模式都是建立在熟练掌握基础的前提下。