设计模式完整笔记(通俗易懂版)(OpenClaw生成)
前排提醒:全文内容皆为OpenClaw生成,没有喂其他材料,内容准确性仅供参考。
设计模式完整笔记(通俗易懂版)
软考中级软件设计师考试专用 | GoF 23种设计模式
一、设计模式是什么
设计模式 = 套路,是前人总结的"这类问题就这样解决"的最佳实践。
就像武侠小说的"招式",记住套路就能见招拆招。
设计模式分为3大类:
-
创建型:对象怎么创建出来
-
结构型:对象怎么组装起来
-
行为型:对象怎么分工合作
二、创建型模式(5种)
1. 单例模式(Singleton)⭐⭐⭐
解决什么问题:我只需要一个对象,全世界都共享这一个。
生活类比
-
地球只有一颗
-
打印机的打印队列只有一份
代码实现(Java)
// 方式一:饿汉式(立即加载)
class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {} // 私有构造函数
public static Singleton getInstance() {
return instance;
}
}
// 方式二:懒汉式(延迟加载)
class SingletonLazy {
private static SingletonLazy instance;
private SingletonLazy() {}
public static synchronized SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}
// 使用
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2); // true,都是同一个对象
考试要点
-
构造函数私有
-
只有一个实例
-
全局访问点
2. 工厂方法模式(Factory Method)⭐⭐⭐
解决什么问题:对象创建太复杂,封装起来,不让调用者直接new。
生活类比
-
你去工厂买车,不需要知道零件怎么组装
-
直接说"我要买轿车"或"我要买卡车"
代码实现(Java)
// 产品接口
interface Phone {
void call();
}
// 具体产品
class iPhone implements Phone {
public void call() {
System.out.println("用iPhone打电话");
}
}
class AndroidPhone implements Phone {
public void call() {
System.out.println("用安卓手机打电话");
}
}
// 工厂接口
interface PhoneFactory {
Phone createPhone();
}
// 具体工厂
class AppleFactory implements PhoneFactory {
public Phone createPhone() {
return new iPhone();
}
}
class SamsungFactory implements PhoneFactory {
public Phone createPhone() {
return new AndroidPhone();
}
}
// 使用
public class Main {
public static void main(String[] args) {
PhoneFactory factory = new AppleFactory();
Phone phone = factory.createPhone();
phone.call(); // 输出:用iPhone打电话
}
}
核心思想
"创建对象"抽象化,让子类决定创建什么对象。
3. 抽象工厂模式(Abstract Factory)⭐⭐⭐
解决什么问题:一个工厂能生产一整套相关产品。
生活类比
-
汽车工厂不只生产车身,还生产发动机、轮胎
-
一家人使用苹果全家桶(iPhone + Mac + iPad)
代码实现(Java)
// 产品族A
interface Button {
void render();
}
interface Checkbox {
void render();
}
// 产品族A的具体产品
class WindowsButton implements Button {
public void render() { System.out.println("Windows按钮"); }
}
class WindowsCheckbox implements Checkbox {
public void render() { System.out.println("Windows复选框"); }
}
// 产品族B的具体产品
class MacButton implements Button {
public void render() { System.out.println("Mac按钮"); }
}
class MacCheckbox implements Checkbox {
public void render() { System.out.println("Mac复选框"); }
}
// 抽象工厂
interface GUIFactory {
Button createButton();
Checkbox createCheckbox();
}
// 具体工厂
class WindowsFactory implements GUIFactory {
public Button createButton() { return new WindowsButton(); }
public Checkbox createCheckbox() { return new WindowsCheckbox(); }
}
class MacFactory implements GUIFactory {
public Button createButton() { return new MacButton(); }
public Checkbox createCheckbox() { return new MacCheckbox(); }
}
// 使用
public class Main {
public static void main(String[] args) {
GUIFactory factory = new WindowsFactory();
Button btn = factory.createButton();
btn.render(); // Windows按钮
}
}
工厂方法 vs 抽象工厂(对比!)
| 特征 | 工厂方法 | 抽象工厂 |
|---|---|---|
| 创建什么 | 一种产品 | 一族产品 |
| 工厂结构 | 一个方法 | 多个方法(一族) |
| 复杂度 | 简单 | 复杂 |
| 适用场景 | 产品种类固定 | 产品族(多个相关产品) |
记忆口诀:
-
工厂方法 = "一个方法产一种"
-
抽象工厂 = "一个工厂产一套"
4. 建造者模式(Builder)⭐⭐
解决什么问题:对象太复杂,构造函数参数太多,用链式调用更清晰。
生活类比
-
麦当劳点餐:汉堡 + 可乐 + 薯条 = 一个套餐
-
可以单独选每一样
代码实现(Java)
// 产品:电脑
class Computer {
private String cpu;
private String gpu;
private String memory;
private String storage;
// 私有构造函数(只能用Builder创建)
private Computer(Builder builder) {
this.cpu = builder.cpu;
this.gpu = builder.gpu;
this.memory = builder.memory;
this.storage = builder.storage;
}
@Override
public String toString() {
return "Computer{cpu='" + cpu + "', gpu='" + gpu +
"', memory='" + memory + "', storage='" + storage + "'}";
}
// 建造者
static class Builder {
private String cpu = "默认CPU";
private String gpu = "默认GPU";
private String memory = "默认内存";
private String storage = "默认硬盘";
public Builder cpu(String cpu) {
this.cpu = cpu;
return this; // 链式调用
}
public Builder gpu(String gpu) {
this.gpu = gpu;
return this;
}
public Builder memory(String memory) {
this.memory = memory;
return this;
}
public Builder storage(String storage) {
this.storage = storage;
return this;
}
public Computer build() {
return new Computer(this);
}
}
}
// 使用
public class Main {
public static void main(String[] args) {
Computer gamingPC = new Computer.Builder()
.cpu("Intel i9")
.gpu("RTX 4090")
.memory("64GB")
.storage("2TB SSD")
.build();
Computer officePC = new Computer.Builder()
.cpu("Intel i5")
.memory("16GB")
.build();
System.out.println(gamingPC);
// Computer{cpu='Intel i9', gpu='RTX 4090', memory='64GB', storage='2TB SSD'}
System.out.println(officePC);
// Computer{cpu='Intel i5', gpu='默认GPU', memory='16GB', storage='默认硬盘'}
}
}
5. 原型模式(Prototype)⭐
解决什么问题:复制一个对象,不暴露创建细节。
生活类比
-
细胞分裂:从一个细胞复制出另一个
-
复印文件:复印机复制文件
代码实现(Java)
// 原型接口
interface Cloneable {
Cloneable clone();
}
// 具体原型
class Student implements Cloneable {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public Student clone() {
return new Student(this.name, this.age);
}
@Override
public String toString() {
return "Student{name='" + name + "', age=" + age + "}";
}
}
// 使用
public class Main {
public static void main(String[] args) {
Student original = new Student("张三", 20);
Student copy = original.clone();
System.out.println(original); // Student{name='张三', age=20}
System.out.println(copy); // Student{name='张三', age=20}
System.out.println(original == copy); // false,不是同一个对象
}
}
三、结构型模式(7种)
6. 适配器模式(Adapter)⭐⭐⭐
解决什么问题:接口不兼容,加个"转换器"让他们能一起工作。
生活类比
-
手机充电头:欧标插头 → 转接头 → 中国插座
-
翻译:把A语言翻译成B语言
代码实现(Java)
// 目标接口(你想要什么)
interface MediaPlayer {
void play(String filename);
}
// 已存在的类(你有的是什么)
class MP3Player {
public void playMP3(String file) {
System.out.println("播放MP3: " + file);
}
}
// 适配器(转换器)
class MediaAdapter implements MediaPlayer {
private MP3Player mp3Player;
public MediaAdapter() {
this.mp3Player = new MP3Player();
}
@Override
public void play(String filename) {
// 把MediaPlayer的play转换为MP3Player能理解的playMP3
mp3Player.playMP3(filename);
}
}
// 使用
public class Main {
public static void main(String[] args) {
MediaPlayer player = new MediaAdapter();
player.play("song.mp3"); // 输出:播放MP3: song.mp3
}
}
7. 装饰器模式(Decorator)⭐⭐⭐
解决什么问题:功能要动态增加,但不是用继承(避免类爆炸)。
生活类比
-
手机壳 + 挂件 = 给手机加装饰
-
咖啡 + 牛奶 + 糖 = 逐步加料
代码实现(Java)
// 基础接口
interface Coffee {
String getDescription();
double getCost();
}
// 基础实现
class SimpleCoffee implements Coffee {
@Override
public String getDescription() {
return "浓缩咖啡";
}
@Override
public double getCost() {
return 20.0;
}
}
// 装饰器基类
abstract class CoffeeDecorator implements Coffee {
protected Coffee coffee;
public CoffeeDecorator(Coffee coffee) {
this.coffee = coffee;
}
}
// 具体装饰器:加牛奶
class MilkDecorator extends CoffeeDecorator {
public MilkDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() + " + 牛奶";
}
@Override
public double getCost() {
return coffee.getCost() + 5.0;
}
}
// 具体装饰器:加糖
class SugarDecorator extends CoffeeDecorator {
public SugarDecorator(Coffee coffee) {
super(coffee);
}
@Override
public String getDescription() {
return coffee.getDescription() + " + 糖";
}
@Override
public double getCost() {
return coffee.getCost() + 2.0;
}
}
// 使用
public class Main {
public static void main(String[] args) {
// 浓缩咖啡
Coffee coffee = new SimpleCoffee();
System.out.println(coffee.getDescription() + " = " + coffee.getCost());
// 浓缩咖啡 = 20.0
// 加牛奶
coffee = new MilkDecorator(coffee);
System.out.println(coffee.getDescription() + " = " + coffee.getCost());
// 浓缩咖啡 + 牛奶 = 25.0
// 再加糖
coffee = new SugarDecorator(coffee);
System.out.println(coffee.getDescription() + " = " + coffee.getCost());
// 浓缩咖啡 + 牛奶 + 糖 = 27.0
}
}
适配器 vs 装饰器(对比!)
| 特征 | 适配器 | 装饰器 |
|---|---|---|
| 目的 | 让不兼容的能一起工作 | 给对象动态加功能 |
| 关系 | "转换器" | "包装" |
| 调用方式 | 调用转换后的方法 | 委托给被包装对象 |
| 使用场景 | 旧系统接口 → 新需求 | 功能扩展 |
记忆口诀:
-
适配器 = "转换插头"
-
装饰器 = "套包装"
8. 代理模式(Proxy)⭐⭐⭐
解决什么问题:不能直接访问对象,通过代理来控制访问。
生活类比
-
房产中介:买家 → 中介 → 房东
-
VPN:电脑 → 代理服务器 → 目标网站
代码实现(Java)
// 真实主题(真正做事的人)
class RealImage {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("从磁盘加载: " + filename);
}
public void display() {
System.out.println("显示图片: " + filename);
}
}
// 代理(控制访问)
class ImageProxy {
private String filename;
private RealImage realImage; // 延迟加载
public ImageProxy(String filename) {
this.filename = filename;
}
public void display() {
// 懒加载:第一次才加载真实对象
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
// 使用
public class Main {
public static void main(String[] args) {
ImageProxy proxy = new ImageProxy("大图片.jpg");
System.out.println("--- 创建代理完毕 ---");
// 此时没有加载真实图片
proxy.display(); // 第一次调用才加载
// 从磁盘加载: 大图片.jpg
// 显示图片: 大图片.jpg
proxy.display(); // 第二次直接用缓存
// 显示图片: 大图片.jpg
}
}
9. 组合模式(Composite)⭐⭐
解决什么问题:树形结构,整体和部分用同一套接口。
生活类比
-
文件夹里有文件,也有子文件夹
-
公司有部门,部门里还有子部门
代码实现(Java)
// 抽象组件
abstract class FileSystemComponent {
protected String name;
public FileSystemComponent(String name) {
this.name = name;
}
abstract void display(String indent);
}
// 叶子(文件)
class File extends FileSystemComponent {
public File(String name) {
super(name);
}
@Override
void display(String indent) {
System.out.println(indent + "- 文件: " + name);
}
}
// 容器(文件夹)
class Folder extends FileSystemComponent {
private List<FileSystemComponent> children = new ArrayList<>();
public Folder(String name) {
super(name);
}
public void add(FileSystemComponent component) {
children.add(component);
}
@Override
void display(String indent) {
System.out.println(indent + "+ 文件夹: " + name);
for (FileSystemComponent child : children) {
child.display(indent + " ");
}
}
}
// 使用
public class Main {
public static void main(String[] args) {
Folder root = new Folder("C盘");
Folder docs = new Folder("文档");
Folder pictures = new Folder("图片");
docs.add(new File("简历.docx"));
docs.add(new File("报告.pdf"));
pictures.add(new File("风景.jpg"));
root.add(docs);
root.add(pictures);
root.display("");
// + 文件夹: C盘
// + 文件夹: 文档
// - 文件: 简历.docx
// - 文件: 报告.pdf
// + 文件夹: 图片
// - 文件: 风景.jpg
}
}
10. 外观模式(Facade)⭐⭐
解决什么问题:子系统太复杂,给一个统一的入口。
生活类比
-
电视遥控器:一个按钮控制电源、音量、频道
-
一键下单:内部调用N个接口,外部只看到一个接口
代码实现(Java)
// 子系统A
class CPU {
public void start() { System.out.println("CPU启动"); }
public void shutdown() { System.out.println("CPU关闭"); }
}
// 子系统B
class Memory {
public void load() { System.out.println("内存加载"); }
public void refresh() { System.out.println("内存刷新"); }
}
// 子系统C
class Disk {
public void read() { System.out.println("磁盘读取"); }
public void write() { System.out.println("磁盘写入"); }
}
// 外观类(统一入口)
class ComputerFacade {
private CPU cpu;
private Memory memory;
private Disk disk;
public ComputerFacade() {
this.cpu = new CPU();
this.memory = new Memory();
this.disk = new Disk();
}
public void startComputer() {
System.out.println("=== 开机启动 ===");
cpu.start();
memory.load();
disk.read();
System.out.println("=== 开机完成 ===");
}
public void shutdownComputer() {
System.out.println("=== 关机 ===");
disk.write();
memory.refresh();
cpu.shutdown();
}
}
// 使用
public class Main {
public static void main(String[] args) {
ComputerFacade computer = new ComputerFacade();
computer.startComputer();
// === 开机启动 ===
// CPU启动
// 内存加载
// 磁盘读取
// === 开机完成 ===
computer.shutdownComputer();
}
}
11. 桥接模式(Bridge)⭐⭐
解决什么问题:两个维度独立变化,互不影响。
生活类比
-
手机品牌(华为、苹果)× 功能(打电话、发短信)
-
形状(圆形、方形)× 颜色(红色、蓝色)
代码实现(Java)
// 维度1:品牌(抽象)
abstract class PhoneBrand {
protected PhoneSoftware software; // 桥接到另一个维度
public void setSoftware(PhoneSoftware software) {
this.software = software;
}
abstract void launch();
}
// 维度2:软件(抽象)
interface PhoneSoftware {
void run();
}
// 具体品牌
class HuaweiPhone extends PhoneBrand {
@Override
void launch() {
System.out.print("华为手机启动: ");
software.run();
}
}
class ApplePhone extends PhoneBrand {
@Override
void launch() {
System.out.print("苹果手机启动: ");
software.run();
}
}
// 具体软件
class WeChat implements PhoneSoftware {
@Override
public void run() {
System.out.println("微信运行中");
}
}
class TikTok implements PhoneSoftware {
@Override
public void run() {
System.out.println("抖音运行中");
}
}
// 使用 - 两个维度可以自由组合
public class Main {
public static void main(String[] args) {
PhoneBrand huawei = new HuaweiPhone();
PhoneBrand apple = new ApplePhone();
huawei.setSoftware(new WeChat());
huawei.launch(); // 华为手机启动: 微信运行中
huawei.setSoftware(new TikTok());
huawei.launch(); // 华为手机启动: 抖音运行中
apple.setSoftware(new WeChat());
apple.launch(); // 苹果手机启动: 微信运行中
}
}
适配器 vs 桥接 vs 装饰器(对比!)
| 模式 | 目的 | 关系 | 编译时/运行时 |
|---|---|---|---|
| 适配器 | 让不兼容的能一起工作 | "转换器" | 运行时 |
| 桥接 | 两个维度独立变化 | "桥接" | 编译时 |
| 装饰器 | 动态增加功能 | "包装" | 运行时 |
四、行为型模式(11种)
12. 观察者模式(Observer)⭐⭐⭐
解决什么问题:一个对象变化,通知所有依赖它的对象。
生活类比
-
微信公众号:作者发文章 → 所有订阅者收到通知
-
气象站:温度变化 → 所有显示板自动更新
代码实现(Java)
// 主题接口
interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyAll();
}
// 具体主题
class WeatherStation implements Subject {
private List<Observer> observers = new ArrayList<>();
private float temperature;
public void setTemperature(float temperature) {
this.temperature = temperature;
notifyAll(); // 温度变化,通知所有观察者
}
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyAll() {
for (Observer o : observers) {
o.update(temperature);
}
}
}
// 观察者接口
interface Observer {
void update(float temperature);
}
// 具体观察者
class PhoneDisplay implements Observer {
@Override
public void update(float temperature) {
System.out.println("手机显示: 温度=" + temperature + "°C");
}
}
class TVDisplay implements Observer {
@Override
public void update(float temperature) {
System.out.println("电视显示: 当前温度 " + temperature + "°C");
}
}
// 使用
public class Main {
public static void main(String[] args) {
WeatherStation station = new WeatherStation();
Observer phone = new PhoneDisplay();
Observer tv = new TVDisplay();
station.attach(phone);
station.attach(tv);
station.setTemperature(25.5f);
// 手机显示: 温度=25.5°C
// 电视显示: 当前温度 25.5°C
station.setTemperature(30.0f);
// 手机显示: 温度=30.0°C
// 电视显示: 当前温度 30.0°C
}
}
13. 策略模式(Strategy)⭐⭐⭐
解决什么问题:不同的算法/策略可以互换。
生活类比
-
出行方式:开车、坐地铁、骑自行车
-
支付方式:微信、支付宝、现金
代码实现(Java)
// 策略接口
interface PaymentStrategy {
void pay(double amount);
}
// 具体策略
class WeChatPay implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("微信支付 ¥" + amount);
}
}
class AliPay implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("支付宝支付 ¥" + amount);
}
}
class CashPay implements PaymentStrategy {
@Override
public void pay(double amount) {
System.out.println("现金支付 ¥" + amount);
}
}
// 环境类(使用策略)
class ShoppingCart {
private List<Double> prices = new ArrayList<>();
private PaymentStrategy strategy; // 可以随时切换
public void addPrice(double price) {
prices.add(price);
}
public void setPaymentStrategy(PaymentStrategy strategy) {
this.strategy = strategy;
}
public void checkout() {
double total = prices.stream().mapToDouble(Double::doubleValue).sum();
strategy.pay(total);
}
}
// 使用
public class Main {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
cart.addPrice(100);
cart.addPrice(50);
cart.addPrice(30);
// 用微信支付
cart.setPaymentStrategy(new WeChatPay());
cart.checkout(); // 微信支付 ¥180.0
// 换支付宝
cart.setPaymentStrategy(new AliPay());
cart.checkout(); // 支付宝支付 ¥180.0
}
}
策略模式 vs 状态模式(对比!)
| 特征 | 策略模式 | 状态模式 |
|---|---|---|
| 关注点 | 算法/行为可以互换 | 对象内部状态决定行为 |
| 切换方式 | 外部指定 | 内部自动切换 |
| 关系 | 平等,可互换 | 状态决定下一个状态 |
记忆口诀:
-
策略 = "你选算法"
-
状态 = "状态自己变"
14. 命令模式(Command)⭐⭐
解决什么问题:把"请求"封装成对象,可以撤销、排队。
生活类比
-
遥控器:按下"开灯"按钮 → 灯亮了
-
餐厅点单:服务员记下订单 → 厨师做菜
代码实现(Java)
// 命令接口
interface Command {
void execute();
void undo(); // 支持撤销
}
// 具体命令
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
@Override
public void execute() {
light.on();
}
@Override
public void undo() {
light.off();
}
}
class Light {
public void on() { System.out.println("灯亮了"); }
public void off() { System.out.println("灯灭了"); }
}
// 调用者(遥控器)
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
public void pressUndo() {
command.undo();
}
}
// 使用
public class Main {
public static void main(String[] args) {
Light light = new Light();
Command lightOn = new LightOnCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton(); // 灯亮了
remote.pressUndo(); // 灯灭了
}
}
15. 模板方法模式(Template Method)⭐⭐
解决什么问题:算法骨架固定,某些步骤由子类实现。
生活类比
-
做菜流程:准备 → 烹饪 → 装盘(固定)
-
具体做什么菜,子类决定
代码实现(Java)
// 抽象父类(定义骨架)
abstract class Beverage {
// 模板方法(算法骨架)
public final void makeBeverage() {
boilWater(); // 1. 烧水(固定)
brew(); // 2. 冲泡(子类实现)
pourInCup(); // 3. 倒杯(固定)
addCondiments(); // 4. 加调料(子类实现)
}
// 固定步骤
private void boilWater() {
System.out.println("烧水");
}
private void pourInCup() {
System.out.println("倒杯");
}
// 子类实现步骤
abstract void brew();
abstract void addCondiments();
}
// 具体子类:茶
class Tea extends Beverage {
@Override
void brew() {
System.out.println("冲泡茶叶");
}
@Override
void addCondiments() {
System.out.println("加柠檬");
}
}
// 具体子类:咖啡
class Coffee extends Beverage {
@Override
void brew() {
System.out.println("冲泡咖啡粉");
}
@Override
void addCondiments() {
System.out.println("加糖和奶");
}
}
// 使用
public class Main {
public static void main(String[] args) {
Beverage tea = new Tea();
tea.makeBeverage();
// 烧水
// 冲泡茶叶
// 倒杯
// 加柠檬
System.out.println("---");
Beverage coffee = new Coffee();
coffee.makeBeverage();
// 烧水
// 冲泡咖啡粉
// 倒杯
// 加糖和奶
}
}
16. 迭代器模式(Iterator)⭐⭐
解决什么问题:遍历集合不用知道集合内部结构。
生活类比
-
书架遍历:不管书架怎么排,书一本一本拿
-
电视遥控器的频道切换按钮
代码实现(Java)
// 迭代器接口
interface Iterator {
boolean hasNext();
Object next();
}
// 具体迭代器
class BookIterator implements Iterator {
private BookCollection collection;
private int position = 0;
public BookIterator(BookCollection collection) {
this.collection = collection;
}
@Override
public boolean hasNext() {
return position < collection.getBooks().size();
}
@Override
public Object next() {
return collection.getBooks().get(position++);
}
}
// 集合接口
interface Collection {
Iterator createIterator();
}
// 具体集合
class BookCollection implements Collection {
private List<String> books = new ArrayList<>();
public void addBook(String book) {
books.add(book);
}
public List<String> getBooks() {
return books;
}
@Override
public Iterator createIterator() {
return new BookIterator(this);
}
}
// 使用
public class Main {
public static void main(String[] args) {
BookCollection collection = new BookCollection();
collection.addBook("《设计模式》");
collection.addBook("《算法导论》");
collection.addBook("《编译原理》");
Iterator iterator = collection.createIterator();
while (iterator.hasNext()) {
System.out.println("书: " + iterator.next());
}
// 书: 《设计模式》
// 书: 《算法导论》
// 书: 《编译原理》
}
}
17. 责任链模式(Chain of Responsibility)⭐⭐
解决什么问题:请求一级一级传递,直到有人处理。
生活类比
-
审批流程:主任 → 部长 → 总经理
-
客户投诉:客服 → 组长 → 经理
代码实现(Java)
// 抽象处理者
abstract class Handler {
protected Handler nextHandler;
public void setNextHandler(Handler handler) {
this.nextHandler = handler;
}
public abstract void handleRequest(String request);
}
// 具体处理者
class Director extends Handler {
@Override
public void handleRequest(String request) {
if (request.equals("请假1天")) {
System.out.println("主任审批通过: " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
class Manager extends Handler {
@Override
public void handleRequest(String request) {
if (request.equals("请假3天")) {
System.out.println("经理审批通过: " + request);
} else if (nextHandler != null) {
nextHandler.handleRequest(request);
}
}
}
class Boss extends Handler {
@Override
public void handleRequest(String request) {
System.out.println("老板审批: " + request);
}
}
// 使用
public class Main {
public static void main(String[] args) {
Handler director = new Director();
Handler manager = new Manager();
Handler boss = new Boss();
director.setNextHandler(manager);
manager.setNextHandler(boss);
director.handleRequest("请假1天"); // 主任审批
director.handleRequest("请假3天"); // 经理审批
director.handleRequest("请假10天"); // 老板审批
}
}
18. 状态模式(State)⭐⭐
解决什么问题:对象内部状态决定行为,状态自动切换。
代码实现(Java)
// 状态接口
interface State {
void insertCoin(Context context); // 投入硬币
void pushButton(Context context); // 按按钮
void dispense(Context context); // 出商品
}
// 具体状态
class NoCoinState implements State {
@Override
public void insertCoin(Context context) {
System.out.println("硬币已投入");
context.setState(new HasCoinState());
}
@Override
public void pushButton(Context context) {
System.out.println("请先投币");
}
@Override
public void dispense(Context context) {}
}
class HasCoinState implements State {
@Override
public void insertCoin(Context context) {
System.out.println("已有硬币,请按按钮");
}
@Override
public void pushButton(Context context) {
System.out.println("按钮已按下,商品准备中");
context.setState(new DispenseState());
}
@Override
public void dispense(Context context) {}
}
class DispenseState implements State {
@Override
public void insertCoin(Context context) {}
@Override
public void pushButton(Context context) {}
@Override
public void dispense(Context context) {
System.out.println("商品已出");
context.setState(new NoCoinState());
}
}
// 环境类(持有状态)
class Context {
private State state = new NoCoinState();
public void setState(State state) {
this.state = state;
}
public void insertCoin() {
state.insertCoin(this);
}
public void pushButton() {
state.pushButton(this);
}
public void dispense() {
state.dispense(this);
}
}
// 使用
public class Main {
public static void main(String[] args) {
Context machine = new Context();
machine.pushButton(); // 请先投币
machine.insertCoin(); // 硬币已投入
machine.pushButton(); // 按钮已按下,商品准备中
machine.dispense(); // 商品已出
}
}
19. 备忘录模式(Memento)⭐
解决什么问题:保存对象状态,随时可恢复。
生活类比
-
游戏存档:打Boss前存档,打输了就读档
-
Word撤销:Ctrl+Z
代码实现(Java)
// 备忘录(存档)
class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
// 原发器(游戏角色)
class GameRole {
private int vitality = 100; // 生命值
private int attack = 50; // 攻击力
// 保存状态
public Memento save() {
return new Memento("生命力:" + vitality + ",攻击力:" + attack);
}
// 恢复状态
public void restore(Memento memento) {
String state = memento.getState();
System.out.println("恢复状态: " + state);
}
public void fight() {
vitality -= 80;
attack += 10;
System.out.println("战斗后: 生命力=" + vitality);
}
public int getVitality() {
return vitality;
}
}
// 管理者(存档管理器)
class Caretaker {
private Memento memento;
public void saveMemento(Memento memento) {
this.memento = memento;
}
public Memento getMemento() {
return this.memento;
}
}
// 使用
public class Main {
public static void main(String[] args) {
GameRole role = new GameRole();
Caretaker caretaker = new Caretaker();
// 打Boss前存档
caretaker.saveMemento(role.save());
System.out.println("存档完成,当前生命力: " + role.getVitality());
// 打Boss
role.fight();
// 打输了,恢复存档
role.restore(caretaker.getMemento());
}
}
20. 享元模式(Flyweight)⭐
解决什么问题:大量相似对象,共享相同部分,只创建不同部分。
生活类比
-
文字处理:文档中所有"字母A"共用同一个字体对象
-
游戏:大量子弹共用同一张贴图
代码实现(Java)
// 享元接口
interface TreeType {
void draw(int x, int y); // 不同位置画同一棵树
}
// 具体享元(共享)
class CommonTree implements TreeType {
private String name; // 内在状态(可共享)
private String color; // 内在状态(可共享)
public CommonTree(String name, String color) {
this.name = name;
this.color = color;
}
@Override
public void draw(int x, int y) {
// x, y 是外在状态(不可共享,每个位置不同)
System.out.println("在(" + x + "," + y + ")绘制" + color + name);
}
}
// 享元工厂
class TreeFactory {
private static Map<String, TreeType> treeTypes = new HashMap<>();
public static TreeType getTreeType(String name, String color) {
String key = name + "-" + color;
if (!treeTypes.containsKey(key)) {
treeTypes.put(key, new CommonTree(name, color));
System.out.println("创建新树: " + key);
}
return treeTypes.get(key);
}
}
// 使用
public class Main {
public static void main(String[] args) {
// 创建10000棵树,但只存储3个享元对象
Random random = new Random();
for (int i = 0; i < 10; i++) {
int x = random.nextInt(100);
int y = random.nextInt(100);
TreeType tree = TreeFactory.getTreeType("松树", "绿色");
tree.draw(x, y);
}
// 输出:创建新树: 松树-绿色
// 然后全部复用同一个对象
}
}
21. 中介者模式(Mediator)⭐
解决什么问题:对象之间不直接通信,通过中介者转发。
生活类比
-
机场调度中心:飞机不直接对话,都找调度中心
-
房产中介:买家和卖家不直接见面,都通过中介
代码实现(Java)
// 中介者接口
interface ChatMediator {
void sendMessage(String msg, User user);
void addUser(User user);
}
// 具体中介者
class ChatRoom implements ChatMediator {
private List<User> users = new ArrayList<>();
@Override
public void addUser(User user) {
users.add(user);
}
@Override
public void sendMessage(String msg, User sender) {
for (User u : users) {
if (u != sender) { // 不发给自己
u.receive(msg);
}
}
}
}
// 同事类(参与者)
class User {
private String name;
private ChatMediator mediator;
public User(String name, ChatMediator mediator) {
this.name = name;
this.mediator = mediator;
}
public void send(String msg) {
System.out.println(name + " 发送: " + msg);
mediator.sendMessage(msg, this);
}
public void receive(String msg) {
System.out.println(name + " 收到: " + msg);
}
}
// 使用
public class Main {
public static void main(String[] args) {
ChatMediator chat = new ChatRoom();
User alice = new User("Alice", chat);
User bob = new User("Bob", chat);
User charlie = new User("Charlie", chat);
chat.addUser(alice);
chat.addUser(bob);
chat.addUser(charlie);
alice.send("大家好!");
// Alice 发送: 大家好!
// Bob 收到: 大家好!
// Charlie 收到: 大家好!
}
}
22. 解释器模式(Interpreter)⭐
解决什么问题:用对象表示语法规则,执行表达式。
生活类比
-
计算器:把 "1 + 2" 解析成语法树,然后计算
-
音乐简谱:把音符翻译成演奏指令
代码实现(Java)
// 表达式接口
interface Expression {
int interpret(Map<String, Integer> context);
}
// 终结符表达式
class NumberExpression implements Expression {
private int number;
public NumberExpression(int number) {
this.number = number;
}
@Override
public int interpret(Map<String, Integer> context) {
return number;
}
}
// 变量表达式
class VariableExpression implements Expression {
private String name;
public VariableExpression(String name) {
this.name = name;
}
@Override
public int interpret(Map<String, Integer> context) {
return context.getOrDefault(name, 0);
}
}
// 加法表达式
class AddExpression implements Expression {
private Expression left;
private Expression right;
public AddExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Map<String, Integer> context) {
return left.interpret(context) + right.interpret(context);
}
}
// 使用:(x + 5) - y
public class Main {
public static void main(String[] args) {
Map<String, Integer> context = new HashMap<>();
context.put("x", 10);
context.put("y", 3);
// (x + 5) - y
Expression expr = new AddExpression(
new VariableExpression("x"),
new NumberExpression(5)
);
int result = expr.interpret(context);
System.out.println("(x + 5) = " + result); // 15
}
}
23. 访问者模式(Visitor)⭐
解决什么问题:对一组对象操作,但不想改对象类。
生活类比
-
体检中心:不同的检查设备(访问者)访问同一个人
-
海关检查:海关人员(访问者)检查不同货物(元素)
代码实现(Java)
// 元素接口
interface Shape {
void accept(Visitor visitor);
}
// 具体元素
class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
@Override
public void accept(Visitor visitor) {
visitor.visitCircle(this);
}
}
class Rectangle implements Shape {
private double width, height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public void accept(Visitor visitor) {
visitor.visitRectangle(this);
}
}
// 访问者接口
interface Visitor {
void visitCircle(Circle circle);
void visitRectangle(Rectangle rectangle);
}
// 具体访问者:计算面积
class AreaVisitor implements Visitor {
@Override
public void visitCircle(Circle circle) {
double area = Math.PI * circle.getRadius() * circle.getRadius();
System.out.println("圆面积: " + area);
}
@Override
public void visitRectangle(Rectangle rectangle) {
double area = rectangle.width * rectangle.height;
System.out.println("矩形面积: " + area);
}
}
// 具体访问者:绘制边框
class DrawVisitor implements Visitor {
@Override
public void visitCircle(Circle circle) {
System.out.println("绘制圆,半径=" + circle.getRadius());
}
@Override
public void visitRectangle(Rectangle rectangle) {
System.out.println("绘制矩形,宽=" + rectangle.width + ",高=" + rectangle.height);
}
}
// 使用
public class Main {
public static void main(String[] args) {
List<Shape> shapes = Arrays.asList(
new Circle(5),
new Rectangle(4, 6)
);
Visitor areaVisitor = new AreaVisitor();
Visitor drawVisitor = new DrawVisitor();
System.out.println("=== 计算面积 ===");
for (Shape s : shapes) {
s.accept(areaVisitor);
}
// 圆面积: 78.54
// 矩形面积: 24.0
System.out.println("=== 绘制 ===");
for (Shape s : shapes) {
s.accept(drawVisitor);
}
}
}
五、全部模式速查表
创建型(5种)
| 模式 | 目的 | 考频 |
|---|---|---|
| 单例 | 只有一个实例 | ★★★ |
| 工厂方法 | 子类决定创建什么 | ★★★ |
| 抽象工厂 | 产一套产品 | ★★★ |
| 建造者 | 链式创建复杂对象 | ★★ |
| 原型 | 复制对象 | ★ |
结构型(7种)
| 模式 | 目的 | 考频 |
|---|---|---|
| 适配器 | 接口转换 | ★★★ |
| 装饰器 | 动态加功能 | ★★★ |
| 代理 | 控制访问 | ★★★ |
| 组合 | 树形结构 | ★★ |
| 外观 | 统一入口 | ★★ |
| 桥接 | 两个维度独立变化 | ★★ |
| 享元 | 共享细粒度对象 | ★ |
行为型(11种)
| 模式 | 目的 | 考频 |
|---|---|---|
| 观察者 | 一对多通知 | ★★★ |
| 策略 | 算法互换 | ★★★ |
| 命令 | 请求封装 | ★★ |
| 模板方法 | 算法骨架 | ★★ |
| 迭代器 | 遍历集合 | ★★ |
| 责任链 | 一级级传递 | ★★ |
| 状态 | 状态决定行为 | ★★ |
| 备忘录 | 保存/恢复状态 | ★ |
| 中介者 | 对象间接通信 | ★ |
| 解释器 | 语法解析 | ★ |
| 访问者 | 操作分离 | ★ |
六、易混模式对比汇总
| 对比组 | 区别 |
|---|---|
| 工厂方法 vs 抽象工厂 | 一个产一种 vs 一个产一套 |
| 策略 vs 状态 | 外部选 vs 内部自动切 |
| 适配器 vs 装饰器 | 转换 vs 包装加功能 |
| 适配器 vs 桥接 | 转换接口 vs 连接两个维度 |
| 装饰器 vs 代理 | 加功能 vs 控制访问 |
| 组合 vs 聚合 | 强整体 vs 弱整体 |
| 观察者 vs 中介者 | 直接通知 vs 间接传话 |
| 命令 vs 策略 | 请求封装 vs 算法互换 |
整理时间:2026-05-22 通俗易懂版
更多推荐

所有评论(0)